You are on page 1of 7

第⼆⼗五章 机器学习

机器学习术语
特征, ⽬标变量, 训练集

测试算法效果: 训练样本集, 测试样本集


2
1
影响机器学习效果的因素
. 特征数据
. 算法模型
开发机器学习应⽤程序的步骤
. 收集数据
. 准备输⼊数据
. 分析数据
. 训练算法
. 测试算法
. 使⽤算法

Numpy 库
⼆维数组 vs 矩阵
import numpy as np

numpy 矩阵的⽣成
a = np.array([[8,8,8,7,8],
[9,8,8,8,9],
[10,9,7,7,8],
[10,9,8,9,9],
[10,8,8,8,8]])
print(a)

⽣成⼀个 5x5 的随机矩阵


c = np.random.rand(5,5)
print(c)
print(a+c)
#矩阵可以进⾏运算

⼆维数组
b = [[8,8,8,7,8],
[9,8,8,8,9],
[10,9,7,7,8],
[10,9,8,9,9],
[10,8,8,8,8]]

d = [[8,8,9,7,8],
[9,8,8,80,9],
[10,9,7,70,8],
[10,9,8,9,9],
[10,8,8,8,8]]
print(b+d)
#⼆维数组不能进⾏运算
#numpy 更符合数学的运算

矩阵的运算 (对每个元素进⾏运算)
print(a**2) # + - * / **
print(a)

获取矩阵内元素的值
print(a[3,3])

修改矩阵内元素的值
a[0,3] = 11
print(a)

倒置矩阵 (⾏列互换)
print(a.T)

KNN 算法 (K-Nearest Neighbor)


优点: 精度⾼, 对异常值不敏感, ⽆数据输⼊假定
缺点: 计算复杂度⾼, 空间复杂度⾼
适⽤数据范围: 数值型和标称型

KNN 算法步骤
. 计算已知类别数据集中的点与当前点之间的距离
. 按距离从⼩到⼤排序
. 选取与当前距离最⼩的 k 个点
. 确定前 k 个点所在类别的出现频率
. 返回前 k 个点出现频率最⾼的类别作为当前点的预测分类

视觉图分析
import matplotlib.pyplot as plt
import numpy as np

a = np.array([[3,104],
[2,100],
[1,81],
[101,10],
[99,5],
[98,2]])
for i in range(3):
plt.plot([18,a[i,0]],[90,a[i,1]],color='r')
plt.scatter([18,a[i,0]],[90,a[i,1]],color='r')
for i in range(3,6):
plt.plot([18,a[i,0]],[90,a[i,1]],color='b')
plt.scatter([18, a[i, 0]], [90, a[i, 1]], color='b')
plt.scatter(18,90 ,color='y')
plt.show()

KNN 算法核⼼代码
def KNN(inX, dataSet, labels, k):
参数使⽤说明
:参数 inX:⽤于分类的输⼊向量 c
:参数 dataSet:输⼊的训练样本集 a
:参数 labels:标签向量 b
:参数 k:⽤于选择最邻近的数⽬ 4
:返回值 return:分类结果

dataSetSize = dataSet.shape[0] #shape 获取 dataSet 的⾏列数,结果为 6


print('dataSetSize:',dataSetSize)
diffMat = np.tile(inX, (dataSetSize,1)) - dataSet #第 1 步:计算已知类别数据集中的点与当前点之间的距离
print(np.tile(inX, (dataSetSize, 1)))
print('diffMat:\n',diffMat)
sqDiffMat = diffMat**2
print('sqDiffMat:\n',sqDiffMat)
sqDistances = sqDiffMat.sum(axis=1)
print('sqDistances:\n',sqDistances)
distances = sqDistances**0.5
print('distances:\n',distances)
sortedDistIndicies = distances.argsort() #第 2 步: 从⼩到⼤排序

print("sortedDistIndicies",sortedDistIndicies)
classCount={} #第 3 步选取与当前点距离最⼩的 k 个点
for i in range(k): # i = 3
voteIlabel = labels[sortedDistIndicies[i]]
print("voteIlabel:",voteIlabel)
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 #第 4 步确定前 k 个点所在类别的出现频率
print('classCount:',classCount)
print('items:',classCount.items())
sortedClassCount = list(classCount.items()) ##第 5 步返回前 k 个点出现频率最⾼的类别作为当前点的预测分类
print('sortedClassCount:',sortedClassCount)
sortedClassCount.sort(key = lambda x:x[1], reverse=True)
print(sortedClassCount)
print(sortedClassCount[0][0])
return sortedClassCount[0][0]

a = np.array([[3,104],
[2,100],
[1,81],
[101,10],
[99,5],
[98,2]])
b = ['爱情⽚','爱情⽚','爱情⽚','动作⽚','动作⽚','动作⽚']
c = np.array([18,90])
result_lab = KNN(c,a,b,4)
print(result_lab)

部分函数解析
shape ⽅法解析
⽤途: 读取数据对象的⾏数和列数, 以元组的形式返回 (只有 array 数据类型能使⽤)
print(a.shape)
print(a.shape[0])
print(b.shape)

tile ⽅法解析
功能是将数组重复 n 次, 构成⼀个新的数组
e = np.array([[1,2,3]])
f = np.array([[1,2,3],[2,3,4]])
print('e 的结果为:\n',np.tile(e,2))
print('f 的结果为:\n',np.tile(f,2))
#假如我们输⼊⼀个元组 (2,2), ⾏和列都会重复
print('f 的结果为:\n',np.tile(f,(2,2)))

sum ⽅法解析
功能: 求和 (可配合 axis 使⽤, 只有 array 数据类型能使⽤)
g = np.array([[1,2,3],[9,8,7]])
print(g.sum())
#axis=None, 将数组 / 矩阵中的元素全部加起来, 得到⼀个和
print(g.sum(axis=1))
#axis=1, 将每⼀⾏的元素相加, 将矩阵压缩为⼀列
print(g.sum(axis=0))
#axis=0, 将每⼀列的元素相加, 将矩阵压缩为⼀⾏

argsort ⽅法解析
功能: 返回数组值从⼩到⼤的索引值 (只有 array 数据类型能使⽤)
h = np.array([3, 1, 2])
print(h.argsort())

sort ⽅法
功能: 对列表进⾏排序
x =[4, 6, 2, 1, -7, 9]
x.sort()
x.sort(reverse = True) #逆序
x.sort(key = abs) #绝对值
x.sort(key = abs,reverse = True)
print(x)

对字典内的元素使⽤ sort ⽅法
d = {'张三':89,'李四':92,'王五':87}
d_list = list(d.items())
print(d_list)
d_list.sort(key = lambda x:x[1],reverse = True)
print(d_list)

KNN 寻找室友项⽬
import numpy as np

从⽂件中读取数据 (数组)
函数功能: 返回特征值和⽬标变量 (标签值)
步骤
. 读取⽂件
. ⼀⾏⼀⾏获取数据
. 通过 split 将数据隔开
. 将前 3 个数据保存在 returnMat 数据对象中, 最后⼀个数据保存在 classLabelVector

def file2matrix(filename,feature_num):
参数使⽤说明
:param filename: 输⼊需要读⼊的⽂件名称,如果⽂件不在代码相同的⽬录下,需要输⼊完整的路径名 + ⽂件名
:feature_num:特征个数
:return:训练集数据和样本标签,是数组类型

fr = open(filename)
numberOfLines = len(fr.readlines()) #获取⽂件的⾏数
# print(numberOfLines)
returnMat = np.zeros((numberOfLines,feature_num))
# print(returnMat)
classLabelVector = [] #prepare labels return
fr = open(filename)
index = 0
for line in fr.readlines():
# print(line, type(line))
line = line.strip()
# print(line, type(line))
listFromLine = line.split('\t')
# print(listFromLine)
returnMat[index,:] = listFromLine[0:feature_num]
classLabelVector.append(int(listFromLine[feature_num:][0]))
index += 1
# print(returnMat,classLabelVector)
return returnMat,classLabelVector
feature_data, label_data = file2matrix('datingTestSet2.txt',3)

归⼀化特征值
每⼀个特征同等重要, 不能因现实数据⼤⼩⽽影响到特征数据的权重

归⼀化可以解决数据的权重问题, 取值范围在 0 到 1 或 -1 到 1

def autoNorm(dataSet):
minVals = dataSet.min(0)
maxVals = dataSet.max(0)
ranges = maxVals - minVals
normDataSet = np.zeros(np.shape(dataSet))
m = dataSet.shape[0]
normDataSet = dataSet - np.tile(minVals, (m,1))
normDataSet = normDataSet/np.tile(ranges, (m,1)) #element wise divide
return normDataSet, ranges, minVals

# new_feature,ranges,minvalus = autoNorm(feature_data)
# print(new_feature,ranges,minvalus)

测试 KNN 数据 (10% 样本集)


def datingClassTest():
hoRatio = 0.10 # hold out 10%
datingDataMat, datingLabels = file2matrix('datingTestSet2.txt',3) # load data setfrom file
m = datingDataMat.shape[0] #m = 1000
numTestVecs = int(m * hoRatio) #numTestVecs = 100
errorCount = 0.0
for i in range(numTestVecs):
classifierResult = KNN(datingDataMat[i, :], datingDataMat[numTestVecs:m, :], datingLabels[numTestVecs:m],
3)
print("KNN 测试结果为: %d, 实际值为: %d" % (classifierResult, datingLabels[i]))
if (classifierResult != datingLabels[i]):
errorCount += 1.0
print("总的错误率为: %f" % (errorCount / float(numTestVecs)))
print(errorCount)

def datingClassTest_new():
hoRatio = 0.10 # hold out 10%
datingDataMat, datingLabels = file2matrix('datingTestSet2.txt',3) # load data setfrom file
normMat, ranges, minVals = autoNorm(datingDataMat)
m = normMat.shape[0]
numTestVecs = int(m * hoRatio)
errorCount = 0.0
for i in range(numTestVecs):
classifierResult = KNN(normMat[i, :], normMat[numTestVecs:m, :], datingLabels[numTestVecs:m], 3)
print("KNN 测试结果为: %d, 实际值为: %d" % (classifierResult, datingLabels[i]))
if (classifierResult != datingLabels[i]): errorCount += 1.0
print("总的错误率为: %f" % (errorCount / float(numTestVecs)))
print(errorCount)

#datingClassTest_new()

通过已经确定好的 KNN 模型, 获取结果


def classify_result():
result_list = ['不喜欢','普通 ','⾮常喜欢']
travel = float(input('请输⼊每年旅⾏的路程:'))
game_time = float(input('请输玩游戏所占百分⽐:'))
junkfood = float(input('请输⼊每个礼拜消耗的零⻝重量 kg:'))
datingDataMat, datingLabels = file2matrix('datingTestSet2.txt', 3)
normMat, ranges, minVals = autoNorm(datingDataMat)
inputarry = np.array([travel,game_time,junkfood])
result_num = KNN((inputarry-minVals)/ranges,normMat,datingLabels,3)
print('赵六对这个⼈是 {}'.format(result_list[result_num-1]))
classify_result()

matplotlib 绘制
# settings --> Tools --> Python Scientific 修改图形展示窗⼝
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

plt.scatter(feature_data[:,0],label_data ,color='r')
plt.title('KNN 展示',fontproperties='SimHei')
plt.plot(feature_data[:,0],feature_data[:,1],'b' '.')
plt.xlabel('x 轴',fontproperties='SimHei')
plt.show()

fig = plt.figure()
ax = fig.gca(projection='3d')
# # print(label_data)
ax.scatter(feature_data[:,0],feature_data[:,1] ,feature_data[:,2],s = 10,c =label_data)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
plt.show()

You might also like