很多时候训练集中不同取值范围的特征值,对计算出来的分类结果影响很大,通常采用的方法是将数值归一化处理,从而对k邻近算法进行改进:
# 归一化处理 def autoNorm(dataSet): if dataSet is None: return None if isinstance(dataSet, list): dataSet = np.array(dataSet) # 最小与最大值矩阵 minX = dataSet.min(0) maxX = dataSet.max(0) # 最大值-最小值 差值矩阵 diffX = maxX - minX # 行数 m = dataSet.shape[0] # newVal = (oldVal - min)/(max - min) normData = (dataSet - np.tile(minX, (m, 1)))/np.tile(diffX, (m, 1)) return normData, minX, diffX # k邻近算法 def classify0(vectorX, dataSet, labels, k, normal = False): if dataSet is None: return None # 检查参数是否合法 if not isinstance(labels, list): throw_error('labels必须为list数组') if not isinstance(k, int): throw_error("k参数必须为整数") # 归一化处理 if normal: dataSet, minX, diffX = autoNorm(dataSet) vectorX = (vectorX - minX)/diffX # 训练集行数 dataSize = dataSet.shape[0] k = dataSize if k > dataSize else k # 构造训练集与样本的差值矩阵 diffMat = np.tile(vectorX, (dataSize, 1)) - dataSet # 求元素的平方 sqDiffMat = diffMat**2 # 行求和开方 sumDiffMat = sqDiffMat.sum(axis=1) # 求出样本到每个训练集的距离 distance = sumDiffMat**0.5 # 获得从小到大的顺序并转换为一维数组 sortDis = np.argsort(distance, axis=0) classCount = {} # 训练集的计数 for i in range(k): lb = labels[sortDis[i]] classCount[lb] = classCount.get(lb, 0) + 1 # 根据距离大小排序 sortClassCount = sortedDictValue(classCount, True) return sortClassCount[0][0]