一、摘要:
本項目通過對學生成績信息讀取和可視化來展現學生學業情況,並建立模型對排名進行預測。
二、選題背景:
學成成績排名預測是一項非常重要的研究內容,本文針對學生成績排名預測的問題,采用多元線性回歸對學生成績進行回歸分析,得到的關於成績排名的回歸模型,能夠有效的對學生的排名進行預測
三、數據說明:
成績數據通過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()
五、總結:
針對學生成績進行了一元線性回歸分析和多元線性回歸,通過擬合曲線可得知成績與排名的關系更加符合多元線性回歸模型。使用該預測模型可在得知學生總分的情況下大致的預測出學生排名。