k近邻算法--改进约会网站配对效果
k近邻算法采用测量数据点之间的距离的方法进行分类。
样本数据集(训练样本集):样本集中每一数据与所属分类存在对应关系。
新数据分类:将新数据与训练样本集中数据进行比较,提取样本集中特征与新数据最相似(数据点之间的距离最小)的k个点,将这k个点的分类标签作为新数据的分类。
下面用该算法来改进约会网站配对效果,代码来源为《机器学习实战》。
训练样本集特征 :
- 每年飞行里程
- 玩游戏所耗时间百分比
- 每周消费冰淇淋量
训练样本集分类 :
- 不喜欢的人
- 魅力一般的人
- 极具魅力的人
训练样本为文本数据集,需要先转化数据格式:
def fileTransfromMatrix(filename): # 该函数输入为文件名字符串 输出为训练样本矩阵和类标签向量 filedata = open(filename) # 打开文件 numberOfLines = len(filedata.readlines()) # 获取文件数据行数 returnMatrxix = np.zeros((numberOfLines,3)) # 创建空的样本矩阵 classLabelVector = [] # 创建空的类标签向量 index = 0 filedata = open(filename) for line in filedata.readlines(): line = line.strip() # strip()函数 删除开头结尾处的空白符 listFromLine = line.split('\t') # 按照制表符对行文本进行切片 生成数组文件 returnMatrxix[index,:] = listFromLine[0:3] # 给样本矩阵的第index行(所有元素)赋值 classLabelVector.append(int(listFromLine[-1])) # 给类标签向量添加该样本类别值 index += 1 return returnMatrxix,classLabelVector
在处理不同取值范围的特征值时,需要先将数值归一化,将取值范围处理到[0,1]之间:
def dataNormal(dataSet): minVals = dataSet.min(0) # 参数0使得函数从所有列中选取最小值 maxVals = dataSet.max(0) ranges = maxVals - minVals normalDataSet = np.zeros(np.shape(dataSet)) m = dataSet.shape[0] normalDataSet = dataSet - np.tile(minVals,(m,1)) normalDataSet = normalDataSet / np.tile(ranges,(m,1)) return normalDataSet,ranges,minerals
接下来就是k近邻算法实现的代码了:
def classifyPerson(inX, dataSet, labels, k): # 输入为预测点 训练样本特征数组 训练样本类别数组 K值 dataSetSize = dataSet.shape[0] # 获取行数 diffMatrix = np.tile(inX, (dataSetSize,1)) - dataSet # 计算预测点与所有欧训练点的差值 sqrDiffMat = diffMatrix**2 sqrDistances = sqrDiffMat.sum(axis=1) # 按行求和 distances = sqrDistances**0.5 # 计算距离 sortedDistIndicies = distances.argsort() # 距离值从小到大排列,返回对应的索引 classCount={} for i in range(k): voteIlabel = labels[sortedDistIndicies[i]] # 从小到大取距离 classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 # 将该点的类别添加到字典中 # sorted函数:返回一个经过排序的列表 # key 指定用于排序的列 # reverse 设置为True时为倒序排列 sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True) return sortedClassCount[0][0]
输入一个新的数据,机器判断所属类别:
def classifyNewPerson(): classList = ['Not interest', 'small interest', 'large interest'] flyMiles = float(input('每年的飞行公里数')) #输入新数据三个特征值 playGames = float(input('视频游戏所花时间占比')) iceCream = float(input('消费的雪糕量')) datingMatrix,classLabels = fileTransfromMatrix('/Users/Desktop/datingTestSet2.txt') normalDataSet,ranges,minVals = dataNormal(datingMatrix) inputData = np.array([flyMiles,playGames,iceCream]) classifierResult = classifyPerson((inputData-minVals)/ranges,normalDataSet,classLabels,3) print('You will probably like this person : ',classList[classifierResult - 1])