机器学习 成绩预测
成绩预测
利用机器学习算法,实现:预测你们班同学的成绩。
要求:
1.任选一门本学期开设的必修课,作为预测对象,必须在本门课程没有考试之前完成论文
2.样本数据的获得与收集,自己提供。
3.使用学过的机器学习算法,
4.编写程序代码
5.训练模型
6.模型测试
# --------------------------转自github--------------------------注:源代码来源于青岛农业大学理信宋彩霞老师,KNN算法;
显示数据集
成绩预测
KNN代码
# -*- coding: UTF-8 -*-from matplotlib.font_manager import FontProperties
import matplotlib.lines as mlines
import matplotlib.pyplot as plt
import numpy as np
import operator"""
函数说明:kNN算法,分类器------------------------约会网站配对效果判定----------------------------------
Parameters:
inX - 用于分类的数据(测试集)
dataSet - 用于训练的数据(训练集)
labes - 分类标签
k - kNN算法参数,选择距离最小的k个点
Returns:
sortedClassCount[0][0] - 分类结果
Modify:
2017-03-24
"""分类
def classify0(inX, dataSet, labels, k):
# numpy函数shape[0]返回dataSet的行数
dataSetSize = dataSet.shape[0]
# 在列向量方向上重复inX共1次(横向),行向量方向上重复inX共dataSetSize次(纵向)
diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
# 二维特征相减后平方
sqDiffMat = diffMat ** 2
# sum()所有元素相加,sum(0)列相加,sum(1)行相加
sqDistances = sqDiffMat.sum(axis=1)
# 开方,计算出距离
distances = sqDistances ** 0.5
# 返回distances中元素从小到大排序后的索引值
sortedDistIndices = distances.argsort()
# 定一个记录类别次数的字典
classCount = {}
for i in range(k):
# 取出前k个元素的类别
voteIlabel = labels[sortedDistIndices[i]]
# dict.get(key,default=None),字典的get()方法,返回指定键的值,如果值不在字典中返回默认值。
# 计算类别次数
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
# python3中用items()替换python2中的iteritems()
# key=operator.itemgetter(1)根据字典的值进行排序
# key=operator.itemgetter(0)根据字典的键进行排序
# reverse降序排序字典
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
# 返回次数最多的类别,即所要分类的类别
return sortedClassCount[0][0]"""
函数说明:打开并解析文件,对数据进行分类:1代表不喜欢,2代表魅力一般,3代表极具魅力
Parameters:
filename - 文件名
Returns:
returnMat - 特征矩阵
classLabelVector - 分类Label向量
Modify:
2017-03-24
"""def file2matrix(filename):
# 打开文件
fr = open(filename)
# 读取文件所有内容
arrayOLines = fr.readlines()
# 得到文件行数
numberOfLines = len(arrayOLines)
# 返回的NumPy矩阵,解析完成的数据:numberOfLines行,3列
returnMat = np.zeros((numberOfLines, 3))
# 返回的分类标签向量
classLabelVector = []
# 行的索引值
index = 0
for line in arrayOLines:
# s.strip(rm),当rm空时,默认删除空白符(包括'\n','\r','\t',' ')
line = line.strip()
# 使用s.split(str="",num=string,cout(str))将字符串根据'\t'分隔符进行切片。
listFromLine = line.split('\t')
# 将数据前三列提取出来,存放到returnMat的NumPy矩阵中,也就是特征矩阵
returnMat[index, :] = listFromLine[0:3]
# 根据文本中标记的喜欢的程度进行分类,1代表不喜欢,2代表魅力一般,3代表极具魅力
if listFromLine[-1] == 'didntLike':
classLabelVector.append(1)
elif listFromLine[-1] == 'smallDoses':
classLabelVector.append(2)
elif listFromLine[-1] == 'largeDoses':
classLabelVector.append(3)
index += 1
return returnMat, classLabelVector"""
函数说明:可视化数据
Parameters:
datingDataMat - 特征矩阵
datingLabels - 分类Label
Returns:
无
Modify:
2017-03-24
"""def showdatas(datingDataMat, datingLabels):
# 设置汉字格式
font = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=14)
# 将fig画布分隔成1行1列,不共享x轴和y轴,fig画布的大小为(13,8)
# 当nrow=2,nclos=2时,代表fig画布被分为四个区域,axs[0][0]表示第一行第一个区域
fig, axs = plt.subplots(nrows=2, ncols=2, sharex=False, sharey=False, figsize=(13, 8))numberOfLabels = len(datingLabels) LabelsColors = [] for i in datingLabels: if i == 1: LabelsColors.append('black') if i == 2: LabelsColors.append('orange') if i == 3: LabelsColors.append('red') # 画出散点图,以datingDataMat矩阵的第一(飞行常客例程)、第二列(玩游戏)数据画散点数据,散点大小为15,透明度为0.5 axs[0][0].scatter(x=datingDataMat[:, 0], y=datingDataMat[:, 1], color=LabelsColors, s=15, alpha=.99) # 设置标题,x轴label,y轴label axs0_title_text = axs[0][0].set_title(u'每学期学习所消耗的时间与每周娱乐所消耗平均时间比值', FontProperties=font) axs0_xlabel_text = axs[0][0].set_xlabel(u'每学期学习所消耗的时间(小时)', FontProperties=font) axs0_ylabel_text = axs[0][0].set_ylabel(u'每周娱乐所消耗平均时间(小时)', FontProperties=font) plt.setp(axs0_title_text, size=9, weight='bold', color='red') plt.setp(axs0_xlabel_text, size=7, weight='bold', color='black') plt.setp(axs0_ylabel_text, size=7, weight='bold', color='black') # 画出散点图,以datingDataMat矩阵的第一(飞行常客例程)、第三列(冰激凌)数据画散点数据,散点大小为15,透明度为0.5 axs[0][1].scatter(x=datingDataMat[:, 0], y=datingDataMat[:, 2], color=LabelsColors, s=15, alpha=.99) # 设置标题,x轴label,y轴label axs1_title_text = axs[0][1].set_title(u'每学期学习所消耗的时间与每天上课平均坐前排平均次数', FontProperties=font) axs1_xlabel_text = axs[0][1].set_xlabel(u'每学期学习所消耗的时间(小时)', FontProperties=font) axs1_ylabel_text = axs[0][1].set_ylabel(u'每天上课平均坐前排平均次数比值', FontProperties=font) plt.setp(axs1_title_text, size=9, weight='bold', color='red') plt.setp(axs1_xlabel_text, size=7, weight='bold', color='black') plt.setp(axs1_ylabel_text, size=7, weight='bold', color='black') # 画出散点图,以datingDataMat矩阵的第二(玩游戏)、第三列(冰激凌)数据画散点数据,散点大小为15,透明度为0.5 axs[1][0].scatter(x=datingDataMat[:, 1], y=datingDataMat[:, 2], color=LabelsColors, s=15, alpha=.99) # 设置标题,x轴label,y轴label axs2_title_text = axs[1][0].set_title(u'每周娱乐所消耗平均时间与每天上课平均坐前排平均次数', FontProperties=font) axs2_xlabel_text = axs[1][0].set_xlabel(u'每周娱乐所消耗平均时间(小时)', FontProperties=font) axs2_ylabel_text = axs[1][0].set_ylabel(u'每天上课平均坐前排平均次数比值', FontProperties=font) plt.setp(axs2_title_text, size=9, weight='bold', color='red') plt.setp(axs2_xlabel_text, size=7, weight='bold', color='black') plt.setp(axs2_ylabel_text, size=7, weight='bold', color='black') # 设置图例 didntLike = mlines.Line2D([], [], color='black', marker='.', markersize=6, label='didntLike') smallDoses = mlines.Line2D([], [], color='orange', marker='.', markersize=6, label='smallDoses') largeDoses = mlines.Line2D([], [], color='red', marker='.', markersize=6, label='largeDoses') # 添加图例 axs[0][0].legend(handles=[didntLike, smallDoses, largeDoses]) axs[0][1].legend(handles=[didntLike, smallDoses, largeDoses]) axs[1][0].legend(handles=[didntLike, smallDoses, largeDoses]) # 显示图片 plt.show()
"""
函数说明:对数据进行归一化
Parameters:
dataSet - 特征矩阵
Returns:
normDataSet - 归一化后的特征矩阵
ranges - 数据范围
minVals - 数据最小值
Modify:
2017-03-24
"""def autoNorm(dataSet):
# 获得数据的最小值 --min(0) 表示返回的是每一列的最小指 ,min(1)是每一行的最小值
minVals = dataSet.min(0)
maxVals = dataSet.max(0)
# 最大值和最小值的范围
ranges = maxVals - minVals
# shape(dataSet)返回dataSet的矩阵行列数
normDataSet = np.zeros(np.shape(dataSet))
# 返回dataSet的行数
m = dataSet.shape[0]
# 原始值减去最小值
normDataSet = dataSet - np.tile(minVals, (m, 1))
# 除以最大和最小值的差,得到归一化数据
normDataSet = normDataSet / np.tile(ranges, (m, 1))
# 返回归一化数据结果,数据范围,最小值
return normDataSet, ranges, minVals"""
函数说明:分类器测试函数
Parameters:
无
Returns:
normDataSet - 归一化后的特征矩阵
ranges - 数据范围
minVals - 数据最小值
Modify:
2017-03-24
"""def datingClassTest():
# 打开的文件名
filename = "datingTestSet.txt"
# 将返回的特征矩阵和分类向量分别存储到datingDataMat和datingLabels中
datingDataMat, datingLabels = file2matrix(filename)
# 取所有数据的百分之十
hoRatio = 0.60
# 数据归一化,返回归一化后的矩阵,数据范围,数据最小值
normMat, ranges, minVals = autoNorm(datingDataMat)# 获得normMat的行数 m = normMat.shape[0] # 百分之十的测试数据的个数 numTestVecs = int(m * hoRatio) # 分类错误计数 errorCount = 0.0 for i in range(numTestVecs): # 前numTestVecs个数据作为测试集,后m-numTestVecs个数据作为训练集 classifierResult = classify0(normMat[i, :], normMat[numTestVecs:m, :], datingLabels[numTestVecs:m], 4) print("分类结果:%d\t真实类别:%d" % (classifierResult, datingLabels[i])) if classifierResult != datingLabels[i]: errorCount += 1.0 print("错误率:%f%%" % (errorCount / float(numTestVecs) * 100))
"""
函数说明:通过输入一个人的三维特征,进行分类输出
Parameters:
无
Returns:
无
Modify:
2017-03-24
"""def classifyPerson():
# 输出结果
resultList = ['不及格', '及格', '优秀']
# 三维特征用户输入
precentTats = float(input("每学期学习所消耗的时间(小时)😊)
ffMiles = float(input("每周娱乐所消耗平均时间(小时)😊)
iceCream = float(input("每天上课平均坐前排平均次数比值:"))
# 打开的文件名
filename = "datingTestSet.txt"
# 打开并处理数据
datingDataMat, datingLabels = file2matrix(filename)
# 训练集归一化
normMat, ranges, minVals = autoNorm(datingDataMat)# 生成NumPy数组,测试集 inArr = np.array([precentTats, ffMiles, iceCream]) # 测试集归一化 norminArr = (inArr - minVals) / ranges # 返回分类结果 classifierResult = classify0(norminArr, normMat, datingLabels, 3) #print(classifierResult) # 打印结果 print("这名同学可能%s" % (resultList[classifierResult-1]))
"""
函数说明:main函数
Parameters:
无
Returns:
无
Modify:
2017-03-24
"""
if name == 'main':# 1、测试代码 filename = "datingTestSet.txt" # 打开并处理数据 datingDataMat, datingLabels = file2matrix(filename) showdatas(datingDataMat, datingLabels) #2、测试代码 datingClassTest() # 正式代码 classifyPerson()
数据
720 8.215452 0.52524 smallDoses 354 68.216555 0.36525 didntLike 100 46.215475 0.00215 didntLike 800 26.21545 0.65154 smallDoses 935 27.02155 0.71525 smallDoses 1500 3.21525 0.91242 largeDoses 1400 4.74522 0.95321 largeDoses 1342 3.21455 0.24565 largeDoses 1440 5.33456 0.81454 largeDoses 187 65.52452 0.35456 didntLike 206 63.34556 0.26443 didntLike 300 70.45221 0.31245 didntLike 600 20.35455 0.76354 smallDoses 825 36.34556 0.24536 smallDoses 1356 6.15322 0.12354 largeDoses 1452 2.15433 0.98724 largeDoses 625 33.15442 0.54675 smallDoses 554 25.64652 0.68443 smallDoses 325 86.21156 0.00054 didntLike 547 86.21156 0.00354 didntLike