• 机器学习实战


    一. 使用k近邻算法改进约会网站的配对效果

    k-近邻算法的一般流程:

    1. 收集数据:可以使用爬虫进行数据的收集,也可以使用第三方提供的免费或收费的数据。一般来讲,数据放在txt文本文件中,按照一定的格式进行存储,便于解析及处理。
    2. 准备数据:使用Python解析、预处理数据。
    3. 分析数据:可以使用很多方法对数据进行分析,例如使用Matplotlib将数据可视化。
    4. 测试算法:计算错误率。
    5. 使用算法:错误率在可接受范围内,就可以运行k-近邻算法进行分类。

    实战内容:

    海伦女士一直使用在线约会网站寻找适合自己的约会对象。尽管约会网站会推荐不同的任选,但她并不是喜欢每一个人。经过一番总结,她发现自己交往过的人可以进行如下分类:

    • 不喜欢的人
    • 魅力一般的人
    • 极具魅力的人

        海伦收集约会数据已经有了一段时间,她把这些数据存放在文本文件datingTestSet.txt中,每个样本数据占据一行,总共有1000行。

        海伦收集的样本数据主要包含以下3种特征:

    • 每年获得的飞行常客里程数
    • 玩视频游戏所消耗时间百分比
    • 每周消费的冰淇淋公升数

     

    完整代码:

      1 import numpy as np
      2 import operator
      3 import matplotlib
      4 import matplotlib.pyplot as plt
      5 
      6 def classify0(inX, dataSet, labels, k):
      7     '''距离计算'''
      8     dataSetSize = dataSet.shape[0]
      9     diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
     10     sqDiffMat = diffMat ** 2
     11     sqDistances = sqDiffMat.sum(axis=1)
     12     distances = sqDistances ** 0.5
     13     sortedDistIndicies = distances.argsort()
     14     classCount = {}
     15     '''选择距离最小的k个点'''
     16     for i in range(k):
     17         voteIlabel = labels[sortedDistIndicies[i]]
     18         classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
     19     '''排序'''
     20     sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
     21     return sortedClassCount[0][0]
     22 
     23 
     24 def file2matrix(filename):
     25     fr = open(filename)             # 打开文件
     26     arrayOfLines = fr.readlines()   # 读取文件所有内容
     27     numberOfLines = len(arrayOfLines)       # 返回文件的行数
     28     returnMat = np.zeros((numberOfLines, 3))
     29     classLabelVector = []
     30     index = 0
     31     for line in arrayOfLines:
     32         line = line.strip()
     33         listFromLine = line.split('	')
     34         returnMat[index, :] = listFromLine[0:3]
     35         # 根据文本中标记的喜欢的程度进行分类,1代表不喜欢,2代表魅力一般,3代表极具魅力
     36         if listFromLine[-1] == 'didntLike':
     37             classLabelVector.append(1)
     38         elif listFromLine[-1] == 'smallDoses':
     39             classLabelVector.append(2)
     40         elif listFromLine[-1] == 'largeDoses':
     41             classLabelVector.append(3)
     42         index += 1
     43     return returnMat, classLabelVector
     44 
     45 datingDataMat, datingLabels = file2matrix('datingTestSet.txt')
     46 
     47 
     48 fig = plt.figure()
     49 ax = fig.add_subplot(111)
     50 ax.scatter(datingDataMat[:, 1], datingDataMat[:, 2], 15.0 * np.array(datingLabels), 15.0 * np.array(datingLabels))
     51 plt.show()
     52 
     53 
     54 def autoNorm(dataSet):
     55     '''归一化特征值:利用公式 newValue = (oldValue - min) / (max - min), 这个公式可以将任意取值范围的特征值转化为0到1区间的值'''
     56     normDataSet = np.zeros(np.shape(dataSet))
     57     m = dataSet.shape[0]
     58 
     59     minVals = dataSet.min(0)                # min(0) 表示返回矩阵中所有列的最小值,当min(1)时,则返回矩阵中所有行的最小值
     60     maxVals = dataSet.max(0)
     61     ranges = maxVals - minVals
     62 
     63     normDataSet = dataSet - np.tile(minVals, (m, 1))
     64     normDataSet = normDataSet / np.tile(ranges, (m, 1))
     65     return normDataSet, ranges, minVals
     66 normMat, ranges, minVals = autoNorm(datingDataMat)
     67 
     68 
     69 def datingClassTest():
     70     hoRatio = 0.10      # 取所有数据的百分之10
     71 
     72     filename = 'datingTestSet.txt'
     73     datingDataMat, datingLabels = file2matrix(filename)
     74     normMat, ranges, minVals = autoNorm(datingDataMat)
     75 
     76     m = normMat.shape[0]
     77     numTestVes = int(m * hoRatio)       # 测试集数量
     78     errorCount = 0.0        # 错误的次数
     79     for i in range(numTestVes):
     80         # 前100个数据作为测试集,后900个数据作为训练集
     81         classifierResult = classify0(normMat[i, :], normMat[numTestVes:m, :], datingLabels[numTestVes:m], 4)
     82         print('分类结果: %d, 真实类别: %d'%(classifierResult, datingLabels[i]))
     83 
     84         if (classifierResult != datingLabels[i]):
     85             errorCount += 1.0
     86     print('错误率: %f%%' % (errorCount / float(numTestVes) * 100))
     87 datingClassTest()
     88 
     89 
     90 def classifyPerson():
     91     resultList = ['讨厌', '有些喜欢', '非常喜欢']
     92     percentTats = float(input('玩视频游戏所耗时间百分比:'))
     93     ffMiles = float(input('每年获得的飞行常客里程数:'))
     94     iceCream = float(input('每周消费的冰淇淋公升数:'))
     95 
     96     filename = 'datingTestSet.txt'
     97     datingDataMat, datingLabels = file2matrix(filename)
     98     normMat, ranges, minVals = autoNorm(datingDataMat)
     99 
    100     inArr = np.array([ffMiles, percentTats, iceCream])
    101     classifierResult = classify0((inArr - minVals) / ranges, normMat, datingLabels, 4)
    102 
    103     print('你可能%s这个人' % (resultList[classifierResult - 1]))
    104 
    105 classifyPerson()

    运行结果:

    二. sklearn手写数字识别系统

    为了简单起见,这里构造的系统只能识别数字0到9,需要识别的数字已经使用图形处理软件,处理成具有相同的色彩和大小①:宽高是32像素×32像素的黑白图像。尽管采用文本格式存储图像不能有效地利用内存空间,但是为了方便理解,我们还是将图像转换为文本格式。

    接下来,我们将使用强大的第三方Python科学计算库Sklearn构建手写数字系统。

    import numpy as np
    import operator
    from os import listdir
    from sklearn.neighbors import KNeighborsClassifier as KNN
    
    def img2Vector(filename):
        '''将32*32的二进制图像转换为1*1024向量'''
    
        # 创建1*1024 的零向量
        returnVect = np.zeros((1, 1024))
        # 打开文件
        fr = open(filename)
        # 按行读取
        for i in range(32):
            # 读一行数据
            lineStr = fr.readline()
            # 每一行的前32个元素依次添加到returnVect中
            for j in range(32):
                returnVect[0, 32 * i + j] = int(lineStr[j])
    
        # 返回转换后的1*1024向量
        return returnVect
    
    
    def handwritingClassTest():
        '''手写数字分类测试'''
    
        # 测试集的Labels
        hwLabels = []
        # 返回trainingDigits目录下的文件名
        trainingFileList = listdir('trainingDigits')
        # 返回文件夹下文件的个数
        m = len(trainingFileList)
        # 初始化训练的Mat矩阵,测试集
        trainingMat = np.zeros((m, 1024))
        # 从文件名中解析出训练集的类别
        for i in range(m):
            # 获得文件的名字
            fileNameStr = trainingFileList[i]
            # 获得分类的数字
            classNumber = int(fileNameStr.split('_')[0])
            # 将获得的类别添加到hwLabels中
            hwLabels.append(classNumber)
            # 将每一个文件的1*1024数据存储到trainingMat矩阵中
            trainingMat[i, :] = img2Vector('trainingDigits/%s' % (fileNameStr))
        # 构建KNN分类器
        neigh = KNN(n_neighbors=3, algorithm='auto')
        # 拟合模型,trainingMat为训练矩阵,hwLabels为对应的标签
        neigh.fit(trainingMat,hwLabels)
        # 返回testDigits目录下的文件列表
        testFileList = listdir('testDigits')
        # 错误检测计数
        errorCount = 0.0
        # 测试集的数量
        mTest = len(testFileList)
        # 从文件中解析出测试集的类别并进行分类
        for i in range(mTest):
            # 获得文件的名字
            fileNameStr = testFileList[i]
            # 获得分类的数字
            classNumber = int(fileNameStr.split('_')[0])
            # 获得测试集的1*1024向量,用于训练
            vectorUnderTest = img2Vector('testDigits/%s' % (fileNameStr))
            # 获得预测结果
            classifierResult = neigh.predict(vectorUnderTest)
    
            print('分类返回结果为:%d	真是结果为:%d' % (classifierResult, classNumber))
    
            if classifierResult != classNumber:
                errorCount += 1.0
        print('总共错了 %d 个数据
    错误率为:%f%%' % (errorCount, errorCount / mTest * 100))
    
    
    handwritingClassTest()

    运行结果:

  • 相关阅读:
    re
    response.xpath
    response.css
    mongovue无法显示collection的问题
    window下安装scrapy
    openCV 图片的处理
    sql server 日期时间操作
    怎样在visual studio 2005 让客户端的recv函数不阻塞
    c# winform 程序用126邮箱发邮件
    MiniDump类笔记
  • 原文地址:https://www.cnblogs.com/lpgit/p/9651253.html
Copyright © 2020-2023  润新知