2017-01-12 3 views
0

Ich versuche, verschiedene Distanz Berechnungsmethoden und verschiedene Wahlsysteme in k-Nächsten Nachbarn-Algorithmus zu vergleichen. Derzeit ist mein Problem, dass egal was ich mache precision_recall_fscore_support Methode von scikit-learn ergibt genau die gleichen Ergebnisse für Präzision, Rückruf und fscore. Warum das? Ich habe es auf verschiedenen Datensätzen versucht (Iris, Glas und Wein). Was mache ich falsch? Der Code so weit:Präzision, Rückruf, F1-Score gleich mit sklearn

#!/usr/bin/env python3 
from collections import Counter 
from data_loader import DataLoader 
from sklearn.metrics import precision_recall_fscore_support as pr 
import random 
import math 
import ipdb 

def euclidean_distance(x, y): 
    return math.sqrt(sum([math.pow((a - b), 2) for a, b in zip(x, y)])) 

def manhattan_distance(x, y): 
    return sum(abs([(a - b) for a, b in zip(x, y)])) 

def get_neighbours(training_set, test_instance, k): 
    names = [instance[4] for instance in training_set] 
    training_set = [instance[0:4] for instance in training_set] 
    distances = [euclidean_distance(test_instance, training_set_instance) for training_set_instance in training_set] 
    distances = list(zip(distances, names)) 
    print(list(filter(lambda x: x[0] == 0.0, distances))) 
    sorted(distances, key=lambda x: x[0]) 
    return distances[:k] 

def plurality_voting(nearest_neighbours): 
    classes = [nearest_neighbour[1] for nearest_neighbour in nearest_neighbours] 
    count = Counter(classes) 
    return count.most_common()[0][0] 

def weighted_distance_voting(nearest_neighbours): 
    distances = [(1/nearest_neighbour[0], nearest_neighbour[1]) for nearest_neighbour in nearest_neighbours] 
    index = distances.index(min(distances)) 
    return nearest_neighbours[index][1] 

def weighted_distance_squared_voting(nearest_neighbours): 
    distances = list(map(lambda x: 1/x[0]*x[0], nearest_neighbours)) 
    index = distances.index(min(distances)) 
    return nearest_neighbours[index][1] 

def main(): 
    data = DataLoader.load_arff("datasets/iris.arff") 
    dataset = data["data"] 
    # random.seed(42) 
    random.shuffle(dataset) 
    train = dataset[:100] 
    test = dataset[100:150] 
    classes = [instance[4] for instance in test] 
    predictions = [] 
    for test_instance in test: 
     prediction = weighted_distance_voting(get_neighbours(train, test_instance[0:4], 15)) 
     predictions.append(prediction) 
    print(pr(classes, predictions, average="micro")) 

if __name__ == "__main__": 
    main() 

Antwort

1

Das Problem ist, dass Sie den "Mikro" Durchschnitt verwenden.

Wie bereits erwähnt here:

Wie in der Dokumentation steht geschrieben: „Beachten Sie, dass für‚micro‘-averaging in einer mehrklassige Einstellung gleich Präzision, Rückruf erzeugen und [Bild: F], während "Gewichtete" Mittelung kann einen F-Wert erzeugen, der nicht zwischen Präzision und Abruf ist. " http://scikit-learn.org/stable/modules/model_evaluation.html

Aber wenn Sie eine Mehrheit Label fallen, die Etiketten-Parameter verwendet wird, dann Mikro-Mittelungs unterscheidet sich von Genauigkeit und Präzision unterscheidet sich von Rückruf.