机器学习 成绩预测

成绩预测

利用机器学习算法,实现:预测你们班同学的成绩。

要求:

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

佳俊提醒你:别搜了,同学,200多人都抄重了

posted @ 2022-05-04 19:35  骑码的佳俊  阅读(1459)  评论(1编辑  收藏  举报