一、摘要:
本项目通过对学生成绩信息读取和可视化来展现学生学业情况,并建立模型对排名进行预测。
二、选题背景:
学成成绩排名预测是一项非常重要的研究内容,本文针对学生成绩排名预测的问题,采用多元线性回归对学生成绩进行回归分析,得到的关于成绩排名的回归模型,能够有效的对学生的排名进行预测
三、数据说明:
成绩数据通过Excel表格函数批量生成。
四、实施过程及代码:
1 import pandas as pd 2 import numpy as np 3 import matplotlib.pyplot as plt 4 plt.rcParams['font.sans-serif']=['SimHei']#这两句作用为防止中文乱码 5 plt.rcParams['axes.unicode_minus']=False 6 path = r'D:\program\逻辑回归录取预测\成绩表.xlsx' 7 data = pd.read_excel(path, sheet_name = '工作表1',usecols = [i for i in range(0,16)]) 8 # data['列名称'] = 1 9 data.head()
1 print(len(data.index.values)) 2 # 行索引 3 print(data.index.values) 4 # 列数 5 print(len(data.columns.values)) 6 # 列索引 7 print(data.columns.values)
查看每一门课程的平均分 ,通过观察柱状图可看出每个课程平均成绩均在74-76范围内,说明每门课学生掌握的程度和老师的教学质量无太大差别
1 course_name = data.columns.values[2:] 2 course_score = [] 3 for name in course_name: 4 sum = 0 5 for score in data[name]: 6 sum+=score 7 course_score.append(sum/len(data[name])) 8 print(course_score) 9 plt.subplot(221) 10 plt.bar(course_name[:4], course_score[:4]) 11 plt.tight_layout() 12 plt.title('课程平均分',fontsize=10) 13 plt.xlabel('课程') 14 plt.ylabel('平均分') 15 16 plt.subplot(222) 17 plt.bar(course_name[4:7], course_score[4:7]) 18 plt.tight_layout() 19 plt.title('课程平均分',fontsize=10) 20 plt.xlabel('课程') 21 plt.ylabel('平均分') 22 23 plt.subplot(223) 24 plt.bar(course_name[7:9], course_score[7:9]) 25 plt.tight_layout() 26 plt.title('课程平均分',fontsize=10) 27 plt.xlabel('课程') 28 plt.ylabel('平均分') 29 30 plt.subplot(224) 31 plt.bar(course_name[9:11], course_score[9:11]) 32 plt.tight_layout() 33 plt.title('课程平均分',fontsize=10) 34 plt.xlabel('课程') 35 plt.ylabel('平均分') 36 plt.show()
求出总分以便进行排名
1 org_score = [] 2 sum_score = [] 3 for i in range(len(data.index.values)): 4 a = data.loc[i].values 5 sum = 0 6 for score in a[2:]: 7 sum+=score 8 org_score.append(sum) 9 sum_score.append(sum) 10
1 org_score[:10]
将求得的总分添加进成绩表格
1 data['总分'] = org_score 2 data.head()
对总分求均值,查看总分分布情况,通过观察趋势图可以看出学生成绩大致服从均值为1049的正态分布
1 sum_s = 0 2 for i in org_score: 3 sum_s+=i 4 print(sum_s/len(data.index.values)) 5 xuhao = [] 6 pingjunfen = [] 7 for i in range(len(data.index.values)): 8 xuhao.append(i+1) 9 pingjunfen.append(sum_s/len(data.index.values)) 10 print(len(xuhao)) 11 print(len(pingjunfen))
1 fig,ax = plt.subplots() 2 ax.scatter(xuhao,pingjunfen,color='r') 3 ax.plot(xuhao,org_score,color='y') 4 plt.title('学生平均分分布') 5 plt.legend(('个人平均分','总体平均分'),loc='upper left') 6 plt.show()
计算排名并添加进表格
1 #对总分进行从高到低排序 2 sum_score.sort(reverse=True) 3 sum_score[:20]
1 score_list = [] 2 rank = [] 3 for i in range(1,len(data.index.values)+1): 4 rank.append(i)
1 rank[:20]
1 len(rank)
1 len(sum_score)
1 for i in range(len(sum_score)):#得到分数与对应排名的表格 2 score_list.append(sum_score[i]) 3 score_list.append(rank[i])
1 score_list[:20]
1 len(score_list)
1 paiming = []#存放排名信息 2 for i in range(len(org_score)): 3 if org_score[i] in score_list: 4 paiming.append(score_list[score_list.index(org_score[i])+1])
1 paiming
1 len(paiming)
1 data['排名'] = paiming[:2029]#将排名信息添加进表格 2 data.head()
1 path = r'D:\program\逻辑回归录取预测\成绩表-排名.xlsx' 2 pd.DataFrame(data).to_excel(path, sheet_name='Sheet1', index=False, header=True)#保存修改后的表格
建立线性回归函数,进行训练和预测
1 final_org = [] 2 for i in sum_score: 3 final_org.append([i])
1 final_org
1 #定义线性回归函数 2 ''' 3 线性回归算法 4 ''' 5 class LinearRegression_1(): 6 def __init__(self): #1.新建变量 7 self.w = None 8 9 def fit(self, X, y): #2.训练集的拟合 10 X = np.insert(X, 0, 1, axis=1) #增加一个维度 11 # print (X.shape) 12 X_ = np.linalg.inv(X.T.dot(X)) #公式:求X的转置(.T)与X矩阵相乘(.dot(X)),再求其逆矩阵(np.linalg.inv()) 13 self.w = X_.dot(X.T).dot(y) #上述公式与X的转置进行矩阵相乘,再与y进行矩阵相乘 14 15 def predict(self, X): #3.测试集的测试反馈 16 X = np.insert(X, 0, 1, axis=1) #增加一个维度 17 y_pred = X.dot(self.w) #X与self.w所表示的矩阵相乘 18 return y_pred
1 #画出排名和成绩对应的变化趋势图。可以看出大概在950-1100的范围其趋势图接近一条直线 2 fig,ax = plt.subplots() 3 ax.scatter(sum_score,rank) 4 plt.title('Real Data') 5 plt.legend(('Data Points','Data Points'),loc='upper right') 6 plt.xlabel('分数') 7 plt.ylabel('排名') 8 plt.show()
1 #确认训练数据和测试数据 2 paiming_train = rank[200:1200] 3 score_train = sum_score[200:1200] 4 paiming_real = rank[1200:1800] 5 score_test = final_org[1200:1800]
1 #确认训练数据和测试数据 2 paiming_train_1 = rank[200:1200] 3 score_train_1 = final_org[200:1200] 4 paiming_real_1 = rank[1200:1800] 5 score_test_1 = final_org[1200:1800]
1 r = LinearRegression_1()#建立线性回归模型 2 r.fit(score_train_1,paiming_train_1)#训练 3 paiming_test = r.predict(score_test_1)#将测试数据放入模型进行预测
1 #画出实际数据与预测数据的趋势图,可以看出在分数990-1040区间实际与预测值大致相同 2 fig,ax = plt.subplots() 3 ax.plot(score_test,paiming_test,color='r') 4 ax.scatter(score_test,paiming_real,color='b') 5 plt.legend(('LinearRegressionl','Real Data'),loc='upper right') 6 plt.xlabel('score') 7 plt.ylabel('rank') 8 plt.show()
上述线性回归模型只在大部分区间使用,为了顾及更多数据我们调整容量即使用二次函数来进行拟合,二次函数拟合的准确率大于刚才的一次函数模型,可以覆盖更多的区间
1 import numpy as np 2 import matplotlib.pyplot as plt 3 from sklearn.linear_model import LinearRegression 4 from sklearn.linear_model import Lasso 5 from sklearn.linear_model import Ridge 6 x_data = np.array(sum_score) 7 y_data = np.array(rank) 8 x_data = x_data.reshape(-1,1) 9 y_data = y_data.reshape(-1,1) 10 X2 = np.hstack([x_data ** 3,x_data ** 2, x_data]) 11 print(X2.shape) 12 model = LinearRegression() # 线性回归 13 model.fit(X2,y_data) 14 y_pre = model.predict(X2) 15 t = np.arange(len(x_data)) 16 print(model.coef_) 17 print(model.intercept_) 18 print(model.score(X2 ,y_data)) 19 plt.plot(x_data,y_pre,color='r') 20 plt.scatter(x_data, y_data) 21 plt.legend(('Pridict','Data Points'),loc='upper right') 22 plt.show()
完整代码:
1 import pandas as pd 2 import numpy as np 3 import matplotlib.pyplot as plt 4 plt.rcParams['font.sans-serif']=['SimHei']#这两句作用为防止中文乱码 5 plt.rcParams['axes.unicode_minus']=False 6 path = r'D:\program\逻辑回归录取预测\成绩表.xlsx' 7 data = pd.read_excel(path, sheet_name = '工作表1',usecols = [i for i in range(0,16)]) 8 # data['列名称'] = 1 9 data.head() 10 11 print(len(data.index.values)) 12 # 行索引 13 print(data.index.values) 14 # 列数 15 print(len(data.columns.values)) 16 # 列索引 17 print(data.columns.values) 18 19 20 course_name = data.columns.values[2:] 21 course_score = [] 22 for name in course_name: 23 sum = 0 24 for score in data[name]: 25 sum+=score 26 course_score.append(sum/len(data[name])) 27 print(course_score) 28 plt.subplot(221) 29 plt.bar(course_name[:4], course_score[:4]) 30 plt.tight_layout() 31 plt.title('课程平均分',fontsize=10) 32 plt.xlabel('课程') 33 plt.ylabel('平均分') 34 35 plt.subplot(222) 36 plt.bar(course_name[4:7], course_score[4:7]) 37 plt.tight_layout() 38 plt.title('课程平均分',fontsize=10) 39 plt.xlabel('课程') 40 plt.ylabel('平均分') 41 42 plt.subplot(223) 43 plt.bar(course_name[7:9], course_score[7:9]) 44 plt.tight_layout() 45 plt.title('课程平均分',fontsize=10) 46 plt.xlabel('课程') 47 plt.ylabel('平均分') 48 49 plt.subplot(224) 50 plt.bar(course_name[9:11], course_score[9:11]) 51 plt.tight_layout() 52 plt.title('课程平均分',fontsize=10) 53 plt.xlabel('课程') 54 plt.ylabel('平均分') 55 plt.show() 56 57 org_score = [] 58 sum_score = [] 59 for i in range(len(data.index.values)): 60 a = data.loc[i].values 61 sum = 0 62 for score in a[2:]: 63 sum+=score 64 org_score.append(sum) 65 sum_score.append(sum) 66 67 68 org_score[:10] 69 70 data['总分'] = org_score 71 data.head() 72 73 sum_s = 0 74 for i in org_score: 75 sum_s+=i 76 print(sum_s/len(data.index.values)) 77 xuhao = [] 78 pingjunfen = [] 79 for i in range(len(data.index.values)): 80 xuhao.append(i+1) 81 pingjunfen.append(sum_s/len(data.index.values)) 82 print(len(xuhao)) 83 print(len(pingjunfen)) 84 85 fig,ax = plt.subplots() 86 ax.scatter(xuhao,pingjunfen,color='r') 87 ax.plot(xuhao,org_score,color='y') 88 plt.title('学生平均分分布') 89 plt.legend(('个人平均分','总体平均分'),loc='upper left') 90 plt.show() 91 92 #对总分进行从高到低排序 93 sum_score.sort(reverse=True) 94 sum_score[:20] 95 96 score_list = [] 97 rank = [] 98 for i in range(1,len(data.index.values)+1): 99 rank.append(i) 100 101 rank[:20] 102 103 len(rank) 104 105 len(sum_score) 106 107 for i in range(len(sum_score)):#得到分数与对应排名的表格 108 score_list.append(sum_score[i]) 109 score_list.append(rank[i]) 110 111 score_list[:20] 112 113 len(score_list) 114 115 paiming = []#存放排名信息 116 for i in range(len(org_score)): 117 if org_score[i] in score_list: 118 paiming.append(score_list[score_list.index(org_score[i])+1]) 119 120 paiming 121 122 len(paiming) 123 124 data['排名'] = paiming[:2029]#将排名信息添加进表格 125 data.head() 126 127 path = r'D:\program\逻辑回归录取预测\成绩表-排名.xlsx' 128 pd.DataFrame(data).to_excel(path, sheet_name='Sheet1', index=False, header=True)#保存修改后的表格 129 130 final_org = [] 131 for i in sum_score: 132 final_org.append([i]) 133 134 final_org 135 136 #定义线性回归函数 137 ''' 138 线性回归算法 139 ''' 140 class LinearRegression_1(): 141 def __init__(self): #1.新建变量 142 self.w = None 143 144 def fit(self, X, y): #2.训练集的拟合 145 X = np.insert(X, 0, 1, axis=1) #增加一个维度 146 # print (X.shape) 147 X_ = np.linalg.inv(X.T.dot(X)) #公式:求X的转置(.T)与X矩阵相乘(.dot(X)),再求其逆矩阵(np.linalg.inv()) 148 self.w = X_.dot(X.T).dot(y) #上述公式与X的转置进行矩阵相乘,再与y进行矩阵相乘 149 150 def predict(self, X): #3.测试集的测试反馈 151 X = np.insert(X, 0, 1, axis=1) #增加一个维度 152 y_pred = X.dot(self.w) #X与self.w所表示的矩阵相乘 153 return y_pred 154 155 #画出排名和成绩对应的变化趋势图。可以看出大概在950-1100的范围其趋势图接近一条直线 156 fig,ax = plt.subplots() 157 ax.scatter(sum_score,rank) 158 plt.title('Real Data') 159 plt.legend(('Data Points','Data Points'),loc='upper right') 160 plt.xlabel('分数') 161 plt.ylabel('排名') 162 plt.show() 163 164 #确认训练数据和测试数据 165 paiming_train = rank[200:1200] 166 score_train = sum_score[200:1200] 167 paiming_real = rank[1200:1800] 168 score_test = final_org[1200:1800] 169 170 #确认训练数据和测试数据 171 paiming_train_1 = rank[200:1200] 172 score_train_1 = final_org[200:1200] 173 paiming_real_1 = rank[1200:1800] 174 score_test_1 = final_org[1200:1800] 175 176 r = LinearRegression_1()#建立线性回归模型 177 r.fit(score_train_1,paiming_train_1)#训练 178 paiming_test = r.predict(score_test_1)#将测试数据放入模型进行预测 179 180 #画出实际数据与预测数据的趋势图,可以看出在分数990-1040区间实际与预测值大致相同 181 fig,ax = plt.subplots() 182 ax.plot(score_test,paiming_test,color='r') 183 ax.scatter(score_test,paiming_real,color='b') 184 plt.legend(('LinearRegressionl','Real Data'),loc='upper right') 185 plt.xlabel('score') 186 plt.ylabel('rank') 187 plt.show() 188 189 import numpy as np 190 import matplotlib.pyplot as plt 191 from sklearn.linear_model import LinearRegression 192 from sklearn.linear_model import Lasso 193 from sklearn.linear_model import Ridge 194 x_data = np.array(sum_score) 195 y_data = np.array(rank) 196 x_data = x_data.reshape(-1,1) 197 y_data = y_data.reshape(-1,1) 198 X2 = np.hstack([x_data ** 3,x_data ** 2, x_data]) 199 print(X2.shape) 200 model = LinearRegression() # 线性回归 201 model.fit(X2,y_data) 202 y_pre = model.predict(X2) 203 t = np.arange(len(x_data)) 204 print(model.coef_) 205 print(model.intercept_) 206 print(model.score(X2 ,y_data)) 207 plt.plot(x_data,y_pre,color='r') 208 plt.scatter(x_data, y_data) 209 plt.legend(('Pridict','Data Points'),loc='upper right') 210 plt.show()
五、总结:
针对学生成绩进行了一元线性回归分析和多元线性回归,通过拟合曲线可得知成绩与排名的关系更加符合多元线性回归模型。使用该预测模型可在得知学生总分的情况下大致的预测出学生排名。