Редактировать
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, то есть и другие возможности для сокращения строк кода и ускорения операций.
Мало того, что написание кода таким образом даст лучшую производительность, он также более лаконичен и ближе к исходному математическомувыражения.