机器学习
第一部分 分类
监督学习: 在监督学习的过程中,我们只需要给定输入样本集,机器就可以从中推演出指定目标变量的可能结果。
监督学习一般使用两种类型的目标变量:标称型(如真与假,)和数值型。
第一章 机器学习基础部分
1.关键术语:
使用某个机器学习算法进行分类时,首先要做的是算法训练,即学习如何分类。
我们为算法输入大量已分类的数据作为算法的训练集。训练集是用于训练机器学习算法的数据样本集合。
每个训练样本中有n个特征、一个目标变量。
目标变量是机器学习算法的预测结果,分类算法中目标变量通常是标称型的,回归算法中通常是连续型(或数值型)的。
特征通常是训练样本集的列,他们是独立测量得到的结果,多个特征联系在一起共同组成一个训练样本。
为了测试机器学习算法的效果,通常使用两套独立的样本集:训练数据和测试数据。
2. 机器学习的主要任务
1. 分类问题和回归问题
分类:将实例数据划分到合适的分类中。
回归:预测数值型的数据,如 数据拟合曲线-通过给定的数据点的最优拟合曲线。
分类和回归属于*监督学习*。
2. 无监督学习,数据中没有类别信息,也没有目标值,将数据集合分成由类似的对象组成的多个类的过程被称为聚类;
将寻找描述数据统计值的过程称之为密度估计;
无监督学习可以减少数据的维度。
3.如何选择合适的算法
想要在算法中选择出实际可用的算法,必须考虑两个问题:
1. 使用机器学习算法的目的,想要完成何种任务?
2. 需要分析或收集的数据是什么?
4. 开发机器学习应用程序的步骤
1. 收集数据。
2. 准备输入数据。
3. 分析输入数据。
4. 训练算法。
5. 测试算法。
6. 使用算法。
第二章 k-近邻算法KNN
1.1 k-近邻算法概述
k-近邻算法采用测量不同特征值之间的距离方法进行分类。
优点:精度高、对异常值不敏感、无数据输入假定。
缺点:计算复杂度高、空间复杂度高。
适用数据范围:数值型和标称型。
工作原理:存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每个数据与所属分类的对应关系。输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,之后算法提取出样本集中特征最相似的数据的分类标签。
1.2.实施KNN分类算法
knn伪代码:
1. 计算已知类别数据集中的点与当前点之间的距离;
2. 按照距离递增次序排列;
3. 选取与当前点距离最小的k个点;
4. 确定前k个点所在类别的出现频率;
5. 返回前k个点出现频率最高的类别作为当前点的预测分类。
程序代码
def classify0(inX, dataSet, labels, k):
dataSetSize = dataSet.shape[0]
diffMat = tile(inX, (dataSetSize,1)) - dataSet
sqDiffMat = diffMat**2
sqDistances = sqDiffMat.sum(axis=1)
distances = sqDistances**0.5
sortedDistIndicies = distances.argsort()
classCount={}
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
2.2 示例:使用K-近邻算法改进约会网站的配对效果
2.2.1 准备数据: 从文本中解析数据
数据存放在文本文件datingTestSet2.txt中,每个样本占据一行,共1000行。
样本包括:每年获得的飞行常客里程数
? 玩视频游戏所耗时间百分比
? 每周消费的冰淇淋公升数
程序代码: 将文本记录转换为Numpy的解析程序
def file2matrix(filename):
fr = open(filename)
arrayOLines = fr.readlines()
numberOfLines = len(arratOLines)
returnMat = zeros((numberOfLines, 3))
classLabelVector = []
index = 0
for line in arratOLines:
line = line.strip()
listFromLine = line.split('\t')
returnMat[index, :] = listFromLine[0:3]
classLabelVector.append(int(listFromLine[-1]))
index += 1
return returnMat, classLabelVector
2.2.2 分析数据: 使用Matlotlib创建散点图
import matplotlib
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(datingDatMat[:, 1], datingDataMat[:, 2],15.0*array(datingLabels), 15.0*array(datingLabels))
plt.show()
2.2.3 准备数据: 归一化数值
归一化公式: newValue = (oldValue-min)/(max-min)
min和max分别是数据集中的最小特征值和最大特征值。
在KNN.py中增加一个新函数autoNorm()
def autoNorm(dataSet):
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
2.2.4 测试算法: 作为完整的程序验证分类器
在KNN.py中创建函数datingClassTest()
程序代码:
def datingClassTest():
hoRatio = 0.10
datingDataMat, datingLabels = file2matrix('datingTestSet.txt')
normMat, ranges, minVals = autoNorm(datingDataMat)
m = norMat.shape[0]
numTestVecs = int(m*hoRatio)
errorCount = 0.0
for i in range(numTestVecs):
classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],
datingLabels[numtestVecs:m, 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)))
2.2.5 使用算法: 构建完整可用系统
将下列代码加入KNN.py
def classifyPerson():
resultList = ['not at all','in small doses', 'in large doses']
percentTats = float(raw_input('percentage of time spent playing video games?'))
ffMiles = float(raw_input('frequent flier miles earned per year?'))
iceCream = float(raw_input('liters of 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 personL',resultList[clasifierResult - 1])
2.3 示例:手写识别系统
def handwritingClassTest():
import numpy as np
import os
def img2vector(filename):
returnVect = np.zeros((1, 1024))
fr = open(filename)
for i in range(32):
lineStr = fr.readline()
for j in range(32):
returnVect[0, 32*i+j] = int(lineStr[j])
return returnVect
hwLabels = []
trainingFileList = os.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])
hwLabels.append(classNumStr)
trainingMat[i,:] = img2vector('trainingDigits/%s'%fileNameStr)
testFileList = os.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)
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)))
调用学习:
import KNN
KNN.handwritingClassTest()
第三章 决策树
决策树包含:判断模块、终止模块、分支。
优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据。
缺点:可能会产生过度匹配问题。
使用数据类型:数值型和标称型。
1.1 决策树的构造
创建分支的伪代码函数createBranch():
检测数据集中的每个子项是否属于同一分类:
if so return 类标签
Else
寻找划分数据集的最好特征
划分数据集
创建分支节点
for每个划分的子集
调用函数createBranch并增加返回结果到分支节点中
return 分支节点
决策树的一般流程:
1. 收集数据: 可以使用任何方法。
2. 准备数据: 树构造算法只适用于标称型数据,因此数值型数据必须离散化。
3. 分析数据: 可以使用任何方法,构造树完成之后,我们应该检查图形是否符合预期。
4. 训练算法: 构造树的数据结构。
5. 测试算法: 使用经验树计算错误率。
6. 使用算法: 此步骤可以适用于任何监督学习算法,而使用决策树可以更好地理解数据的内在含义。
1.2 信息增益
划分数据集的最大原则是:将无序的数据变得更加有序。
在划分数据集之前之后信息发生的变化成为信息增益。
集合信息的度量方式成为香农熵或者简称为熵。
trees.py:
from math import log
def calcShannonEnt(dataSet):
numEntries = len(dataSet)
labelCounts = {}
for featVec in dataSet:
currentLabel = featVec[-1]
if currentLabel not in labelCounts.keys():
labelCounts[currentLabel] = 0
labelCounts[currentLabel] += 1
shannonEnt = 0.0
for ket in labelCounts:
prob = float(labelCounts[key])/numEntries
shannonEnt -= prob * log(prob, 2)
return shannonEnt
|