1 4

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])

 

posted @ 2017-09-09 15:00  韦木三  阅读(265)  评论(0编辑  收藏  举报