0、引言
- 寫作目的:只是為了學習一下DNN的用法
- 基本思路:
- 首先,將學生成績(平時成績x、期末成績y:csv格式)裝載;
- 接着,將成績數據標准化。(PS:雖然這里的成績已經[0~100]之間了,本文是為了學習DNN,故不省略這一步)
- 接着,將平時成績x,期末成績y進一步拆分(按比例,如20%)為訓練數據和測試數據。PS:測試數據用來檢驗訓練出的模型性能
- 接着,創建DNN模型。依次設置一系列的參數。
- 接着,訓練模型(fit函數)。model1.fit(x_train, y_train)
- 接着,評估模型性能。用測試集數據評估,還可以用訓練集數據。 如果性能不好,則調參(第四步)
- 最后,可以應用所得模型,進行期末成績的預測。
- 實驗環境
- Mac OSX
- python 2
- 應用到的包(好多,缺什么你安裝什么好了,有(很多)時候還會出錯,自己百度、谷歌等可以解決,我花費了1天時間才搞好)
1、裝載數據
- 預先加載包
import csv, os
- 裝載數據,到 score_data ; 標題寫到score_header, 代碼如下:
score_file = 'score.csv'
if not os.path.exists(score_file):
print "File ", score_file, " does not exist!"
else :
score_data = []
with open(score_file) as csvfile:
csv_reader = csv.reader(csvfile)
score_header = next(csv_reader) # 讀取第1行, 不是標題
score_header = next(csv_reader) # 讀取第2行每一列的標題
for row in csv_reader: # 將csv 文件中的數據保存到score_data中
score_data.append(row)
csvfile.close() # 關閉文件
- score_data結果:
2、數據標准化
- 拆分數據集 x(平時成績),y(期末成績;
- 將其標准化。即將輸入區間:$(-\infty , +\infty ) $映射到區間(0,1)
2.1 切片 score_data, 數據導入 x ,y 。代碼:
x , y = [], []
for item in score_data:
x0 , y0 = item[0:13], item[13] # 注意:LL的切片[m:n] ,從 LL[m] ... LL[n-1]
x.append(x0)
y.append(y0)
2.2 標准化
- 應用包:sklearn.preprocessing 中 MinMaxScaler()。 將 x和 y 映射成 [0,1] 區間的值。 代碼:
from sklearn.preprocessing import MinMaxScaler
x_MinMax = MinMaxScaler ()
y_MinMax = MinMaxScaler ()
import numpy as np
y = np.array(y).reshape((len(y), 1))
x = x_MinMax.fit_transform(x)
y = y_MinMax.fit_transform(y)
x.mean(axis =0)
# print x_MinMax.scale_
# print y_MinMax.scale_
# print y_MinMax.inverse_transform([[0.8725]]) # 如果預測值為“0.8725”,則可用 inverse_transform 映射回實際值
-
問題:如何將一個標准化的(預測)值value,再映射回實際值?
- 應用 y_MinMax.inverse_transform([[value]]) 。
-
以y為例,顯示top 5 個轉換后的數。
3、數據拆分為訓練集和測試集
- 應用包:sklearn.model_selection 中 train_test_split()。 將 x和 y 按照比例(test_size)拆分。 代碼:
import random
from sklearn.model_selection import train_test_split
np.random.seed(2019)
x_train , x_test , y_train , y_test = train_test_split(x, y, test_size = 0.2)
4、設置DNN模型
-
先引入包:
from sknn.mlp import Regressor, Layer
-
參數設置步驟
- 先設置DNN每層計算方式,先設置每個隱層、最后設置輸出層
- 隱層。設置參數:激活函數(Sigmoid、ReLU: Rectifier)、計算單元數量units
- 輸出層。Layer("Linear")
- 學習速率: learning_rate=0.02
- random_rate = 2019 : 用來再現相同的數據
- 模型允許最大迭代次數:n_iter = 10
- 先設置DNN每層計算方式,先設置每個隱層、最后設置輸出層
-
代碼:
from sknn.mlp import Regressor, Layer
## 模型1,fit1_Sigmoid:激活函數 "Sigmoid"
fit1_Sigmoid = Regressor(layers=[
Layer("Sigmoid", units=6),
Layer("Sigmoid", units=14),
Layer("Linear")],
learning_rate=0.02,
random_state=2019,
n_iter=10)
## 模型2,fit2_ReLU :激活函數 "ReLU"
fit2_ReLU = Regressor(layers=[
Layer("Rectifier", units=6),
Layer("Rectifier", units=14),
Layer("Linear")],
learning_rate=0.02,
random_state=2019,
n_iter=10)
## 模型3,fit3_ReLU:激活函數 "ReLU", 調整迭代次數為100
fit3_ReLU = Regressor(layers=[
Layer("Rectifier", units=6),
Layer("Rectifier", units=14),
Layer("Linear")],
learning_rate=0.02,
random_state=2019,
n_iter=100)
## 模型4,fit4_ReLU:激活函數 "ReLU", 調整迭代次數為100,
## 采用L2正則化,和一個相對小的權重衰減系數0.001來調整期末考試得分模型
fit4_ReLU = Regressor(layers=[
Layer("Rectifier", units=6),
Layer("Rectifier", units=14),
Layer("Linear")],
learning_rate=0.02,
regularize = "L2",
random_state=2019,
weight_decay =0.001,
n_iter=100)
5、訓練模型
- 用函數fit()訓練模型,即使用數據(x_train, y_train),擬合模型。代碼:
print "fitting model right now"
fit1_Sigmoid.fit(x_train,y_train)
fit2_ReLU.fit(x_train,y_train)
fit3_ReLU.fit(x_train,y_train)
fit4_ReLU.fit(x_train,y_train)
6、評估模型
6.0 用預測結果與實際結果的相關性 R的平方來評估模型。
- 引入下面的包 mean_squared_error。 代碼:
from sklearn.metrics import mean_squared_error
6.1 評估模型在訓練集上的表現
pred1_train = fit1_Sigmoid.predict(x_train)
pred2_train = fit2_ReLU.predict(x_train)
pred3_train = fit3_ReLU.predict(x_train)
pred4_train = fit4_ReLU.predict(x_train)
mse_1_train = mean_squared_error(pred1_train, y_train)
mse_2_train = mean_squared_error(pred2_train, y_train)
mse_3_train = mean_squared_error(pred3_train, y_train)
mse_4_train = mean_squared_error(pred4_train, y_train)
print "train ERROR :\n \
mse_1_train = %s \n mse_2_train = %s \n mse_3_train = %s \n mse_4_train = %s "\
%(mse_1_train, mse_2_train,mse_3_train,mse_4_train)
- 運行結果:
6.2 評估模型在測試集上的表現
pred1_test = fit1_Sigmoid.predict(x_test)
pred2_test = fit2_ReLU.predict(x_test)
pred3_test = fit3_ReLU.predict(x_test)
pred4_test = fit4_ReLU.predict(x_test)
mse_1_test = mean_squared_error(pred1_test, y_test)
mse_2_test = mean_squared_error(pred2_test, y_test)
mse_3_test = mean_squared_error(pred3_test, y_test)
mse_4_test = mean_squared_error(pred4_test, y_test)
print "test ERROR :\n \
mse_1_test = %s \n mse_2_test = %s \n mse_3_test = %s \n mse_4_test = %s "\
%(mse_1_test, mse_2_test,mse_3_test,mse_4_test)
- 運行結果:
7、應用模型
-
給出一組平時成績,預測期末成績 y'
-
映射到實際的分數
- 用MinMaxScaler的函數inverse_transform()
- y_MinMax.inverse_transform([[y']])
7.1. 輸入:csv格式數據,存入:x_data
score_file_pred = 'score_pred.csv'
if not os.path.exists(score_file_pred):
print "File ", score_file_pred, " does not exist!"
else :
x_data = []
with open(score_file_pred) as csvfile_pred:
csv_reader = csv.reader(csvfile_pred)
score_header = next(csv_reader) # 讀取第1行, 不是標題
score_header = next(csv_reader) # 讀取第2行每一列的標題
for row in csv_reader: # 將csv 文件中的數據保存到score_data中
x_data.append(row[0:NumberOfPractice])
csvfile_pred.close() # 關閉文件
7.2. 將 x_src 標准化
x_src = x_MinMax.fit_transform(x_data)
x_src.mean(axis =0)
7.3. 應用4個模型預測。
- 得到的預測值:pred1_src、pred2_src、pred3_src、pred4_src
# print "根據平時成績預測期末成績 ......"
pred1_src = fit1_Sigmoid.predict(x_src)
pred2_src = fit2_ReLU.predict(x_src)
pred3_src = fit3_ReLU.predict(x_src)
pred4_src = fit4_ReLU.predict(x_src)
7.4. 將標准化的預測值,映射到實踐值
pred_real1 = y_MinMax.inverse_transform(pred1_src)
pred_real2 = y_MinMax.inverse_transform(pred2_src)
pred_real3 = y_MinMax.inverse_transform(pred3_src)
pred_real4 = y_MinMax.inverse_transform(pred4_src)
# print "期末成績"
# print pred_real1, pred_real2, pred_real3, pred_real4
7.5. 將預測結果,寫到csv文件
- 新建了一個csv文件
# print "期末成績寫入文件... "
with open("score_pred_result.csv", 'w') as f:
result_writer = csv.writer(f)
result_writer.writerow(score_header + ["Pred1","Pred2","Pred3","Pred4"])
i = 0
for row in x_data:
row.append(pred_real1[i])
row.append(pred_real2[i])
row.append(pred_real3[i])
row.append(pred_real4[i])
i = i + 1
result_writer.writerow(row)
f.close() # 關閉文件
附錄1:本次實驗完整的代碼
# -*- coding: utf-8 -*-
# 可以處理指定目錄下的 對應分數的score.csv
import pdb
import csv
import os
# step 1: 裝載數據,到 score_data ; 標題寫到score_header
# 數據集名稱
score_file = 'score.csv'
NumberOfPractice = 13 # 平時作業次數
if not os.path.exists(score_file):
print "File ", score_file, " does not exist!"
else :
score_data = []
with open(score_file) as csvfile:
csv_reader = csv.reader(csvfile)
score_header = next(csv_reader) # 讀取第1行, 不是標題
score_header = next(csv_reader) # 讀取第2行每一列的標題
for row in csv_reader: # 將csv 文件中的數據保存到score_data中
score_data.append(row)
csvfile.close() # 關閉文件
# step 2:拆分數據集 x(平時成績),y(期末成績),並將其標准化
# 2.1 切片 score_data
x , y = [], []
for item in score_data:
x0 , y0 = item[0:NumberOfPractice], item[NumberOfPractice]
x.append(x0)
y.append(y0)
# 2.2 標准化
from sklearn.preprocessing import MinMaxScaler
x_MinMax = MinMaxScaler ()
y_MinMax = MinMaxScaler ()
import numpy as np
y = np.array(y).reshape((len(y), 1))
x = x_MinMax.fit_transform(x)
y = y_MinMax.fit_transform(y)
x.mean(axis =0)
# print x_MinMax.scale_
# print y_MinMax.scale_
# print y_MinMax.inverse_transform([[0.8725]]) # 如果預測值為“0.8725”,則可用 inverse_transform 映射回實際值
## step 3:拆分為訓練集和測試集
import random
from sklearn.model_selection import train_test_split
np.random.seed(2019)
x_train , x_test , y_train , y_test = train_test_split(x, y, test_size = 0.2)
## step 4:創建DNN模型。 PS: 可以創建很多類型的DNN,
from sknn.mlp import Regressor, Layer
## 模型1,fit1_Sigmoid:激活函數 "Sigmoid"
fit1_Sigmoid = Regressor(layers=[
Layer("Sigmoid", units=6),
Layer("Sigmoid", units=14),
Layer("Linear")],
learning_rate=0.02,
random_state=2019,
n_iter=10)
## 模型2,fit2_ReLU :激活函數 "ReLU"
fit2_ReLU = Regressor(layers=[
Layer("Rectifier", units=6),
Layer("Rectifier", units=14),
Layer("Linear")],
learning_rate=0.02,
random_state=2019,
n_iter=10)
## 模型3,fit3_ReLU:激活函數 "ReLU", 調整迭代次數為100
fit3_ReLU = Regressor(layers=[
Layer("Rectifier", units=6),
Layer("Rectifier", units=14),
Layer("Linear")],
learning_rate=0.02,
random_state=2019,
n_iter=100)
## 模型4,fit4_ReLU:激活函數 "ReLU", 調整迭代次數為100,
## 采用L2正則化,和一個相對小的權重衰減系數0.001來調整期末考試得分模型
fit4_ReLU = Regressor(layers=[
Layer("Rectifier", units=6),
Layer("Rectifier", units=14),
Layer("Linear")],
learning_rate=0.02,
regularize = "L2",
random_state=2019,
weight_decay =0.001,
n_iter=100)
## step 5: 用函數fit()訓練模型,即使用數據(x_train, y_train),擬合模型
print "fitting model right now"
fit1_Sigmoid.fit(x_train,y_train)
fit2_ReLU.fit(x_train,y_train)
fit3_ReLU.fit(x_train,y_train)
fit4_ReLU.fit(x_train,y_train)
## step 6: 評估模型。
### 6.0 用預測結果與實際結果的相關性 R的平方來評估模型,引入下面的包 mean_squared_error
from sklearn.metrics import mean_squared_error
### 6.1 評估模型在訓練集上的表現
pred1_train = fit1_Sigmoid.predict(x_train)
pred2_train = fit2_ReLU.predict(x_train)
pred3_train = fit3_ReLU.predict(x_train)
pred4_train = fit4_ReLU.predict(x_train)
mse_1_train = mean_squared_error(pred1_train, y_train)
mse_2_train = mean_squared_error(pred2_train, y_train)
mse_3_train = mean_squared_error(pred3_train, y_train)
mse_4_train = mean_squared_error(pred4_train, y_train)
print "train ERROR :\n \
mse_1_train = %s \n mse_2_train = %s \n mse_3_train = %s \n mse_4_train = %s "\
%(mse_1_train, mse_2_train,mse_3_train,mse_4_train)
### 6.2 評估模型在測試集上的表現
pred1_test = fit1_Sigmoid.predict(x_test)
pred2_test = fit2_ReLU.predict(x_test)
pred3_test = fit3_ReLU.predict(x_test)
pred4_test = fit4_ReLU.predict(x_test)
mse_1_test = mean_squared_error(pred1_test, y_test)
mse_2_test = mean_squared_error(pred2_test, y_test)
mse_3_test = mean_squared_error(pred3_test, y_test)
mse_4_test = mean_squared_error(pred4_test, y_test)
print "test ERROR :\n \
mse_1_test = %s \n mse_2_test = %s \n mse_3_test = %s \n mse_4_test = %s "\
%(mse_1_test, mse_2_test,mse_3_test,mse_4_test)
## step 7: 應用模型s
### 7.1. 輸入:csv格式數據,存入:x_data
print "讀取新數據 ... "
score_file_pred = 'score_pred.csv'
if not os.path.exists(score_file_pred):
print "File ", score_file_pred, " does not exist!"
else :
x_data = []
with open(score_file_pred) as csvfile_pred:
csv_reader = csv.reader(csvfile_pred)
score_header = next(csv_reader) # 讀取第1行, 不是標題
score_header = next(csv_reader) # 讀取第2行每一列的標題
for row in csv_reader: # 將csv 文件中的數據保存到score_data中
x_data.append(row[0:NumberOfPractice])
csvfile_pred.close() # 關閉文件
### 7.2. 將 x_src 標准化
x_src = x_MinMax.fit_transform(x_data)
x_src.mean(axis =0)
### 7.3. 應用4個模型預測。
## 得到的預測值:pred1_src、pred2_src、pred3_src、pred4_src
# print "根據平時成績預測期末成績 ......"
pred1_src = fit1_Sigmoid.predict(x_src)
pred2_src = fit2_ReLU.predict(x_src)
pred3_src = fit3_ReLU.predict(x_src)
pred4_src = fit4_ReLU.predict(x_src)
### 7.4. 將標准化的預測值,映射到實踐值
pred_real1 = y_MinMax.inverse_transform(pred1_src)
pred_real2 = y_MinMax.inverse_transform(pred2_src)
pred_real3 = y_MinMax.inverse_transform(pred3_src)
pred_real4 = y_MinMax.inverse_transform(pred4_src)
# print "期末成績"
# print pred_real1, pred_real2, pred_real3, pred_real4
### 7.5. 將預測結果,寫到csv文件
# print "期末成績寫入文件... "
with open("score_pred_result.csv", 'w') as f:
result_writer = csv.writer(f)
result_writer.writerow(score_header + ["Pred1","Pred2","Pred3","Pred4"])
i = 0
for row in x_data:
row.append(pred_real1[i])
row.append(pred_real2[i])
row.append(pred_real3[i])
row.append(pred_real4[i])
i = i + 1
result_writer.writerow(row)
f.close() # 關閉文件
#