一、摘要:
本项目通过对学生成绩信息读取和可视化来展现学生学业情况,并建立模型对排名进行预测。
二、选题背景:
学成成绩排名预测是一项非常重要的研究内容,本文针对学生成绩排名预测的问题,采用多元线性回归对学生成绩进行回归分析,得到的关于成绩排名的回归模型,能够有效的对学生的排名进行预测
三、数据说明:
成绩数据通过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()
五、总结:
针对学生成绩进行了一元线性回归分析和多元线性回归,通过拟合曲线可得知成绩与排名的关系更加符合多元线性回归模型。使用该预测模型可在得知学生总分的情况下大致的预测出学生排名。