Получение ошибки при реализации алгоритма KNN - PullRequest
0 голосов
/ 14 сентября 2018

Новичок в stackoverflow, а также в программировании, я из истории статистики ниже - реализация алгоритма KNN.Получение ошибки TypeError: unsupported operand type(s) for -: 'str' and 'str'.

Это другие ошибки, которые я получил.Заранее спасибо за ответ.

Файл "knn.py", строка 78, в main ()

Файл "knn.py", строка 71, в основных соседях = getNeighbors (trainingSet, testSet [x], k)

Файл "knn.py", строка 33, в getNeighbors dist = euclideanDistance (testInstance, trainingSet [x], length)

Файл "knn.py", строка 26на расстоянии euclideanDistance + = pow ((instance1 [x] - instance2 [x]), 2)

import csv
import random
import math
import pandas
import numpy

def loadDataset(filename, split, trainingSet=[] , testSet=[]):

    filename = 'data1.csv'
    raw_data = open(filename, 'rt')
    reader = csv.reader(raw_data, delimiter=',', quoting=csv.QUOTE_NONE)
    dataset = list(reader)


    for x in range(len(dataset)-1):
        for y in range(4):
            dataset[x][y] = float(dataset[x][y])
        if random.random() < split:
            trainingSet.append(dataset[x])
        else:
            testSet.append(dataset[x])

def euclideanDistance(instance1, instance2, length):
    distance = 0
    for x in range(length):
        distance += pow((instance1[x] - instance2[x]), 2)
    return math.sqrt(distance)

def getNeighbors(trainingSet, testInstance, k):
    distances = []
    length = len(testInstance)-1
    for x in range(len(trainingSet)):
        dist = euclideanDistance(testInstance, trainingSet[x], length)
        distances.append((trainingSet[x], dist))
    distances.sort(key=operator.itemgetter(1))
    neighbors = []
    for x in range(k):
        neighbors.append(distances[x][0])
    return neighbors

def getResponse(neighbors):
    classVotes = {}
    for x in range(len(neighbors)):
        response = neighbors[x][-1]
        if response in classVotes:
            classVotes[response] += 1
        else:
            classVotes[response] = 1
    sortedVotes = sorted(classVotes.iteritems(), key=operator.itemgetter(1), reverse=True)
    return sortedVotes[0][0]

def getAccuracy(testSet, predictions):
    correct = 0
    for x in range(len(testSet)):
        if testSet[x][-1] == predictions[x]:
            correct += 1
    return (correct/float(len(testSet))) * 100.0

def main():
# prepare data
    trainingSet=[]
    testSet=[]
    split = 0.67
    loadDataset('data1.csv', split, trainingSet, testSet)
    print ('Train set: ' + repr(len(trainingSet)))
    print ('Test set: ' + repr(len(testSet)))
# generate predictions
    predictions=[]
    k = 3
    for x in range(len(testSet)):
        neighbors = getNeighbors(trainingSet, testSet[x], k)
        result = getResponse(neighbors)
        predictions.append(result)
        print('> predicted=' + repr(result) + ', actual=' + repr(testSet[x][-1]))
    accuracy = getAccuracy(testSet, predictions)
    print('Accuracy: ' + repr(accuracy) + '%')

main()

Ответы [ 2 ]

0 голосов
/ 14 сентября 2018

Редактировать

csv.reader возвращает строку по умолчанию.Вам нужно конвертировать соответствующие предметы в поплавки.

Кроме того, вы можете получить кадр данных Pandas напрямую, используя

df = pd.read_csv(filename)

, и получить массив Numpy, если хотите, используя

data = df.values

, и затем работать с этимdata.


Первая строка вашего csv - это, вероятно, заголовок, и вы его не пропускаете.Таким образом, ваш первый обучающий экземпляр на самом деле является строками, которые составляют заголовок, и вы пытаетесь вычесть строки в вашей euclideanDistance функции.

Сказав это, ваш код очень непифонический .

Например,

length = len(testInstance) - 1
for x in range(len(trainingSet)):
    dist = euclideanDistance(testInstance, trainingSet[x], length)
    distances.append((trainingSet[x], dist))

Вам не нужно передавать length, потому что это может быть поиск с использованием функции len внутри euclideanDistance.

Вы можете перебирать экземпляры в trainingSet напрямую

for x in trainingSet:
    dist = euclideanDistance(testInstance, x, length)
    distances.append((x, dist))

или лучше

distances = [(x, euclideanDistance(testInstance, x) for x in trainingSet)]

Аналогично,

neighbors = []
for x in range(k):
    neighbors.append(distances[x][0])

банкапросто будьте

neighbors = [x[0] for x in distances[:k]]

Python также позволяет вам возвращать несколько элементов одновременно, и это крайне плохая практика - возвращаться по ссылке, как это обычно делается в других языках.Так что

def loadDataset(filename, split, trainingSet=[] , testSet=[]):

должно быть

def loadDataset(filename, split):
    trainingSet = []
    testSet = []
    # ...

    return trainingSet, testSet

trainingSet, testSet = loadDataset(filename, ',')

Для такого рода приложений вам следует избегать использования списка Python в этом случае и вместо этого использовать массивы Numpy для хранения ваших данных.Таким образом, многие операции могут быть векторизованы, что значительно повышает производительность.

Например, для вычисления расстояния между testInstance и trainingSet

# I'm deliberately converting them to numpy array but in general 
# you should keep them in this form right from the start
testInstance = np.asarray(testInstance).reshape(1, -1)[:-1] # Your last item is label. Ideally remove them at the beginning
trainingSet = np.vstack(trainingSet)[:, :-1] # Same case as above.

# Here we use broadcasting to obtain difference 
# between each row in trainingSet and testInstance
distances = np.linalg.norm(trainingSet - testInstance, axis=1)**2

Если вам позволено / готовоЕсли использовать Scipy, то есть и другие возможности для сокращения строк кода и ускорения операций.

Мало того, что написание кода таким образом даст лучшую производительность, он также более лаконичен и ближе к исходному математическомувыражения.

0 голосов
/ 14 сентября 2018

Vamsi,

Я заметил, что вы используете numpy и панд.Пока я работаю над отладкой, хочу порекомендовать еще один замечательный пакет - sci-kit learn.

У них уже есть встроенная реализация KNN: http://scikit -learn.org / stable / modules / neighbors.html

РЕДАКТИРОВАТЬ: Я считаю, что естьпроблема приведения в строке 26. Похоже, вы пытаетесь вычесть 2 строки.Я думаю, что это может решить вашу проблему, если вы работаете с целочисленными данными

def euclideanDistance(instance1, instance2, length):
     distance = 0
     for x in range(length):
         distance += pow((int(instance1[x]) - int(instance2[x])), 2)
     return math.sqrt(distance)

Если вы работаете с данными с плавающей запятой, то будет работать следующее:

distance += pow((float(instance1[x]) - float(instance2[x])), 2)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...