《Machine Learning In Action》 中knn部分的代码精简优化
Contact me:
Blog -> https://cugtyt.github.io/blog/index
Email -> cugtyt@qq.com
GitHub -> Cugtyt@GitHub
本系列博客主页及相关见此处
此处粘贴的代码来源为https://github.com/Jack-Cherish/Machine-Learning
1. classify0函数,通过计算距离判断类别,原代码过于繁杂
原代码:
def classify0(inX, dataSet, labels, k):
#numpy函数shape[0]返回dataSet的行数
dataSetSize = dataSet.shape[0]
#在列向量方向上重复inX共1次(横向),行向量方向上重复inX共dataSetSize次(纵向)
diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
#二维特征相减后平方
sqDiffMat = diffMat**2
#sum()所有元素相加,sum(0)列相加,sum(1)行相加
sqDistances = sqDiffMat.sum(axis=1)
#开方,计算出距离
distances = sqDistances**0.5
#返回distances中元素从小到大排序后的索引值
sortedDistIndices = distances.argsort()
#定一个记录类别次数的字典
classCount = {}
for i in range(k):
#取出前k个元素的类别
voteIlabel = labels[sortedDistIndices[i]]
#dict.get(key,default=None),字典的get()方法,返回指定键的值,如果值不在字典中返回默认值。
#计算类别次数
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
#python3中用items()替换python2中的iteritems()
#key=operator.itemgetter(1)根据字典的值进行排序
#key=operator.itemgetter(0)根据字典的键进行排序
#reverse降序排序字典
sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
#返回次数最多的类别,即所要分类的类别
return sortedClassCount[0][0]
问题:
没有利用numpy的broadcasting便利,tile导致无用的扩充,而且类别的提取也有些复杂,使用Counter可以极大简化。
参考修改:
def classify0(inx, dataset, labels, k):
# Compute distance
dist = np.sum((inx - dataset)**2, axis=1)**0.5
# A list that contains k nearest neighbor labels
k_labels = [labels[index] for index in dist.argsort()[0 : k]]
# Use Counter to compute most common label
label = Counter(k_labels).most_common(1)[0][0]
return label
2. autoNorm函数,同样写法复杂
原代码:
def autoNorm(dataSet):
#获得数据的最小值
minVals = dataSet.min(0)
maxVals = dataSet.max(0)
#最大值和最小值的范围
ranges = maxVals - minVals
#shape(dataSet)返回dataSet的矩阵行列数
normDataSet = np.zeros(np.shape(dataSet))
#返回dataSet的行数
m = dataSet.shape[0]
#原始值减去最小值
normDataSet = dataSet - np.tile(minVals, (m, 1))
#除以最大和最小值的差,得到归一化数据
normDataSet = normDataSet / np.tile(ranges, (m, 1))
#返回归一化数据结果,数据范围,最小值
return normDataSet, ranges, minVals
问题:
没有利用numpy的broadcasting便利,tile导致无用的扩充,简单的逻辑实现繁杂
参考修改:
def auto_norm(dataset):
minvalue = np.min(dataset, axis=0)
maxvalue = np.max(dataset, axis=0)
ranges = maxvalue - minvalue
norm_dataset = (dataset - minvalue) / ranges
return norm_dataset, ranges, minvalue
多加利用语言和功能包的特性,能极大简化代码,逻辑也更为清晰,代码更加可读