1、从文件中获取数据
获取训练集的方法有很多,这里介绍的是用文件导入的方法。简单来说,就是从文件中获取到数据,将其加工到一种可以用的格式。
def file2matrix2(filename):
# 根据文件路径获取文件对象
fr = open(filename)
arrayOLines = fr.readlines()
# 获取文件的行数
numberOfLines = len(arrayOLines)
# 利用行数创建一个 numberOfLines行,3列的空矩阵
returnMat = np.zeros((numberOfLines, 3))
# 定义返回的标签
classLabelVector = []
# 定义循环变量
index = 0
for line in arrayOLines:
# 去除字符串左右两边的多余格式,包括\n,空格等
line = line.strip()
# 根据“\t”对数据进行切分
listFromLine = line.split('\t')
# 将数据数据的前三列赋值到新建的行单元中
returnMat[index, :] = listFromLine[0:3]
# 将标签转换成数字
classLabelVector.append(getScore(listFromLine[-1]))
index += 1
return returnMat, classLabelVector
# 将文字转换成数据的字典
def getScore(var):
return {
'didntLike': 1,
'smallDoses': 2,
'largeDoses': 3,
}.get(var, 'error')
这个方法里边有一些需要注意的地方:
2、数据可视化
为了对数据进行分析,可以利用一些可视化的手段将数据制作成不同的图标,便于用户进行分析,这里利用的是matplotlib的pyplot模块,首先利用上边的方法将数据从文件中获取出来,然后画图。具体的代码如下:
def drow_scatter():
# 从文件里边截取出数据和label,这里我用的是相对路径
datingDataMat, datingLabels = KNN.file2matrix2("data/datingTestSet.txt")
# 创建一个模型对象
fig = plt.figure()
# add_subplot是用来画子图的,111中,前两个数字表示行数和列数,也就是11表示的是一行一列。
# 后边的1表示是第几个图。从左到右数。
ax = fig.add_subplot(111)
# 画散点图。前两个参数是散点图的x,y轴的坐标,虽然只有这两组数据可以画出散点图,但是这样的图都是一堆一样的点。
# 所以引入了后边两个参数。第一个是控制点的大小,第二个是控制点的颜色。
ax.scatter(datingDataMat[:, 0], datingDataMat[:, 1], 15.0 * np.array(datingLabels), 15.0 * np.array(datingLabels))
# 展示画好的图形
plt.show()
执行上边的代码可以获得下边的图像:
可以用过matplotlib的api去进一步定制所得的图像,如颜色,大小,标题,坐标轴等,这里不详细描述。
3、特征的规划统一
由上边的图中可以看出两个坐标轴的差距非常巨大。x轴上的数据都是万级,但是y轴的数据是十级。这样的数据差别对于训练算法来说是不利,会增加我们算法的迭代次数,我们需要将所有的指标都缩放到-1~1之间。这样就会需要用到下边的算法:
newValue = (oldValue - min ) / (max - min)
下边我们根据这个原理封装一个将训练集特征进行缩放的算法:
# 特征缩放
def autoNorm(dataSet):
# 求最大最小值
minVals = dataSet.min(0)
maxVals = dataSet.max(0)
# dataSet的范围
ranges = maxVals- minVals
# 新建一个dataSet目的是为了用矩阵运算,这样比较快。
normDataSet = np.zeros(np.shape(dataSet))
# 求出行数
m = dataSet.shape[0]
# 使用“规划统一”的公式是:newValue = (oldValue - min ) / (max - min )
# tile是复制函数,m是纵向复制的次数,1,是横向复制的次数。
normDataSet = dataSet - np.tile(minVals, (m,1))
# 同样的方法用向量求出分母
normDataSet = normDataSet / np.tile(ranges, (m, 1))
return normDataSet, ranges, minVals
通过这个算法可以获取到三个东西:缩放之后的数据、输入的数据范围以及数据的最小值。
4、封装一个分类器
通过上边的操作以及一些封装之后,我们就可以真正地制作一个真实可用的分类器了。本次的数据集中,已经将数据粉成三类。用户可以通过数据自己的指标,获得其所属的分类:
def classify_persion():
#定义一个显示的结果集
resultList = ['not at all', 'in small doses', 'in large doses']
# 询问平均游戏时常
percentTats = float(input('percentage of time spent playing video games?\n'))
# 飞行里程
ffMiles = float(input("frequent flier miles earned per year?\n"))
# 吃雪糕的数量
iceCream = float(input('liters of ice cream consumed per year\n'))
# 从文件导入训练集
datingDatamat, datingLabels = KNN.file2matrix('data/datingTestSet.txt')
# 对训练集进行特征缩放
normMat, ranges, minVals = KNN.autoNorm(datingDatamat)
# 利用输入的数据生成一个矢量
inArr = np.array([ffMiles, percentTats, iceCream])
# 调用分类算法,获取预测标签
classifierResult = KNN.classify((inArr - minVals) / ranges, normMat, datingLabels, 3)
# 告知用户结果
print('You will probably like this person: \n' + resultList[KNN.getScore(classifierResult)-1 ])
这一步,其实是对上边几个步骤的综合,通过收集用户数据,利用训练集训练算法,然后再将用户数据放进去训练集中进行预测。