《机器学习实战》读书笔记第一章&第二章

来源:互联网 发布:手机淘宝看差评 编辑:程序博客网 时间:2024/05/22 05:20

《机器学习实战》(Machine Learning in Action)读书笔记(anaconda平台 python3.6)

第一章 机器学习基础

监督学习:这类算法必须知道预测什么,即目标变量的分类信息
  1. 分类:将实例数据划分到合适的分类中
  2. 回归:预测数值型数据

无监督学习:数据没有类别信息,也不会给定目标值

  1. 聚类:将数据集合分成由类似的对象组成的多个类的过程
  2. 密度估计:寻找描述数据统计值的过程
机器学习开发的步骤:
  1. 收集数据
  2. 准备输入数据
  3. 分析输入数据
  4. 训练算法
  5. 测试算法
  6. 使用算法

第二章 k-近邻算法

k-近邻算法采用测量不同特征值之间的距离方法进行分类,以下为简单样例
头文件引用部分
from numpy import *import operatorimport matplotlibimport matplotlib.pyplot as pltfrom os import listdir
一个简单的样例数据和分类器
def createDataSet():    group = array([        [1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]    ])    labels = ['A', 'A', 'B', 'B']    return group, labelsgroup, labels = createDataSet()def classify0(inX, dataSet, labels, k):    '''    :param inX: 输入向量    :param dataSet: 训练样本集    :param labels: 标签向量    :param k: 距离最近的k的数目    :return: 分类结果    '''    dataSetSize = dataSet.shape[0]#训练样本集中的数据组数    diffMat = tile(inX, (dataSetSize,1)) - dataSet#tile函数创建与dataSet的shape相同的inX的复制集,与dataSet相减用于计算距离    sqDiffMat = diffMat ** 2#将各分量平方    sqDistances = sqDiffMat.sum(axis = 1)#将每条轴上平方后的结果相加    distances = sqDistances ** 0.5#开根号表示距离    sortedDistIndicies = distances.argsort()#返回distance数组从小到大的索引值    classCount = {}    for i in range(k):        votellabel = labels[sortedDistIndicies[i]]#按距离从小到大选取标签        classCount[votellabel] = classCount.get(votellabel, 0) + 1#如果字典中已有该标签,原标签数+1,如果没有,0+1    sortedDistIndicies = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)#按出现次数给标签所在字典排序    print(sortedDistIndicies)    return sortedDistIndicies[0][0]
对于存储在txt中的文件,需要格式化为训练样本矩阵和类标签向量
def file2matrix(filename):    '''    将待处理数据从txt文本变为训练样本矩阵和类标签向量    :param filename:    :return:    '''    fr = open(filename)#打开文件    arrayOfLines = fr.readlines()#读取每行文件    numberOfLines = len(arrayOfLines)#得到文件的行数    returnMat = zeros((numberOfLines, 3))#创建大小为(文件行数,3)的矩阵    classLabelVector = []    index = 0    for line in arrayOfLines:        line = line.strip()#截取掉所有的回车字符        listFromLine = line.split('\t')#用tab符分割line        returnMat[index, :] = listFromLine[0:3]#选取前3个元素存储到特征矩阵中        classLabelVector.append(int(listFromLine[-1]))#将列表的最后一列存储到classLabeVector中        index += 1#对特征数组的下一行进行操作    return returnMat, classLabelVector
用file2matrix读入数据后,用matplotlib库绘图
atingDataMat, datingLabels = file2matrix('datingTestSet2.txt')fig = plt.figure()ax = fig.add_subplot(3,1,1)#将画布分为3行1列,画在第1块ax.scatter(datingDataMat[:, 0], datingDataMat[:, 1],           30.0*array(datingLabels), 15.0*array(datingLabels))#以datingDataMat的第一列\第二列数据画散点图,并给予不同的大小和颜色ay = fig.add_subplot(3,1,2)ay.scatter(datingDataMat[:, 0], datingDataMat[:, 2],           30.0*array(datingLabels), 15.0*array(datingLabels))az = fig.add_subplot(3,1,3)az.scatter(datingDataMat[:, 1], datingDataMat[:, 2],           30.0*array(datingLabels), 15.0*array(datingLabels))plt.show()#通过比较容易得出第一列和第二列数据形成的散点图更容易区分数据点从属的类别


由于特征值拥有不同取值范围,为避免某一特征值对结果的影响过大,需要对数据进行归一化
def autoNorm(dataSet):    '''    归一化,将数字特征值转化为0到1的区间    newValue = (oldValue - min) / (max - min)    :param dataSet:    :return:    '''    minVals = dataSet.min(0)#样本数据中每列的最小值    maxVals = dataSet.max(0)#样本数据中每列的最大值    ranges = maxVals - minVals    normDataSet = zeros(shape(dataSet))#创建新的返回矩阵    m = dataSet.shape[0]    normDataSet = dataSet - tile(minVals, (m, 1))#样本数据均减去每列对应的最小值    normDataSet = normDataSet / tile(ranges, (m, 1))#样本数据均除去每列最大值和最小值的差值,归一化    return normDataSet, ranges, minVals
编写程序测试分类器错误率(书中选取切片为[numTestVecs:m],我认为该切片会导致测试率hoRatio与实际测试数据量成反比,所以改为[0:numTestVecs],如有不同见解欢迎指出)
def datingClassTest():    '''    用于测试分类器效果    :return:    '''    hoRatio = 0.1#测试数据占总数据百分比    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')    normMat, ranges, minvals = autoNorm(datingDataMat)    m = normMat.shape[0]    numTestVecs = int (m * hoRatio)#测试次数    errorCount = 0.0    for i in range(numTestVecs):        classifierResult = classify0(normMat[i, :], normMat[0:numTestVecs, :], \                                     datingLabels[0:numTestVecs], 3)#将测试数据放入分类器中测试        print("The classifier came back with: %d, the real answer is %d"\              % (classifierResult, datingLabels[i]))        if (classifierResult != datingLabels[i]):            errorCount += 1.0#错误计数器        print("the total error rate is: %f" % (errorCount/float(numTestVecs)))#输出当前错误率'''
构建出一个简单的约会网站预测模型
def classifyPerson():    '''    约会网站预测函数    :return:    '''    resultList = ['not at all', 'in small doses', 'in large doses']    percentTats = float(input(\        "percentage of time spent playing video games?"))    ffMiles = float(input("frequent flier miles earned per year?"))    iceCream = float(input("liters or ice cream consumed per year?"))    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')    normMat, ranges, minVals = autoNorm(datingDataMat)#将输入结果作为样本输入向量    inArr = array([ffMiles, percentTats, iceCream])    classifierResult = classify0((inArr - minVals)/ranges, normMat, datingLabels ,3)    print("You will probably like this person:",resultList[classifierResult - 1])
至此,我们完成了基于约会网站数据的分类器
接下来将要实现的是简单的手写识别系统,原理是在二进制存储的图像数据上使用knn,此例仍会沿用上例的头文件引用与classify0函数 
用img2vector存入数据
def img2vector(filename):    '''    将待处理数据从txt存储的二进制图像转换为1*1024的向量    :param filename:    :return:    '''    returnVect = zeros((1, 1024))    fr = open(filename)    for i in range(32):        lineStr = fr.readline()#循环读取32行        for j in range(32):            returnVect[0, 32 * i + j] = int(lineStr[j])#存入数组    return  returnVect
进行分类器的训练和测试
def handwritingClassTest():    hwLabels = []    trainingFileList = listdir('trainingDigits')#列出训练数据集目录下的文件名    m = len(trainingFileList)#训练数据组数    trainingMat = zeros((m, 1024))#创建训练数据大小的矩阵    for i in range(m):        fileNameStr = trainingFileList[i]        fileStr = fileNameStr.split('.')[0]        classNumStr = int(fileStr.split('_')[0])#根据文件名得到真实数据,如0_35.txt表示真实数字为0        hwLabels.append(classNumStr)#根据真实数据确定标志集        trainingMat[i, :] = img2vector('trainingDigits/%s' %fileNameStr)#将二进制图像存入训练矩阵    testFileList = listdir('testDigits')    errorCount = 0.0    mTest = len(testFileList)    for i in range(mTest):        fileNameStr = testFileList[i]        fileStr = fileNameStr.split('.')[0]        classNumStr = int(fileStr.split('_')[0])        vectorUnderTest = img2vector('testDigits/%s' %fileNameStr)#读取测试数据下的二进制图像        classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3)#使用测试数据为输入向量,训练数据为训练矩阵和训练标签,k=3使用分类器        print("the classifier came back with: %d, the real answer is: %d" % (classifierResult, classNumStr))        if(classifierResult != classNumStr):            errorCount += 1.0        print("\nthe total number of errors is : %d" % errorCount)        print("\nthe total error rate is: %f" % (errorCount / float(mTest)))
小结:
k-邻近算法
  • 优点:简单有效
  • 缺点:占用存储空间大(必须保存全部数据集),耗时长(必须对数据集中的每个数据计算距离值)







阅读全文
0 0