【线性回归——从简单构建到实现数据预测】
深度學(xué)習(xí)與神經(jīng)網(wǎng)絡(luò)day03-線性回歸
- 一、簡單的線性回歸
- 1.1、數(shù)據(jù)集的構(gòu)建
- 1.2、模型構(gòu)建
- 1.3、損失函數(shù)
- 1.4、模型優(yōu)化
- 1.5、模型訓(xùn)練
- 1.6、模型評估
- 1.7、樣本數(shù)量和正則化系數(shù)的影響
- 二、多項(xiàng)式回歸
- 1.1、數(shù)據(jù)集的構(gòu)建
- 1.2、模型構(gòu)建
- 1.5、模型訓(xùn)練
- 1.6、模型評估
- 三、嘗試封裝Runner類
- 四、基于線性回歸的波士頓房價(jià)預(yù)測
- 4.1數(shù)據(jù)集介紹
- 4.2數(shù)據(jù)清洗
- 4.2.1缺失值分析
- 4.2.2異常值處理
- 4.3數(shù)據(jù)集的劃分
- 4.4特征工程
- 4.5模型構(gòu)建
- 4.6完善Runner類
- 4.7模型訓(xùn)練
- 4.8 模型預(yù)測
- 后話:一些問題
一、簡單的線性回歸
1.1、數(shù)據(jù)集的構(gòu)建
我們知道線性回歸要實(shí)現(xiàn)的方程式為:
我們通過一個簡單的函數(shù)linear_func來實(shí)現(xiàn)我們的一個簡單的線性回歸,并由此擴(kuò)展到多個特征的線性回歸模型。
linear_func是一個可以構(gòu)建構(gòu)建輸入特征和輸出標(biāo)簽的維度都為1的數(shù)據(jù)集函數(shù)。
function:接下來構(gòu)造產(chǎn)生數(shù)據(jù)集的函數(shù),函數(shù)隨機(jī)產(chǎn)生一個num_data行1列的隨機(jī)數(shù)據(jù)集,并由linear_func確定標(biāo)簽值并添加噪聲值,從而使得數(shù)據(jù)集符合現(xiàn)實(shí)生活中并不那么完美的線性回歸。
import torchdef one_feature_data(func,random_x,num_data,noise=0.0,add_outlier=False,outlier_ratio=0.001):"""函數(shù)功能:根據(jù)給定的函數(shù)來生成簡單的數(shù)據(jù)集輸入:- func: 函數(shù)- random_x: x的取值范圍(list)- num_data: 生成的數(shù)據(jù)集個數(shù)- noise: 添加噪聲的大小,默認(rèn)為0- add_outlier: 是否添加異常點(diǎn),默認(rèn)為False- outlier_ratio: 異常值占比輸出:- X: 特征數(shù)據(jù),shape=[num_data,1]- Y: 標(biāo)簽數(shù)據(jù),shape=[num_data,1]"""#首先生成num_data個隨機(jī)數(shù),范圍在random_x之間X = torch.rand(shape=[num_data])*(random_x[1]-random_x[0])+random_x[0]#產(chǎn)生YY=func(X)#生成高斯分布的標(biāo)簽噪聲,使標(biāo)簽不完美。#用np.random.normal實(shí)現(xiàn)num_data個噪聲點(diǎn),0為均值,noise標(biāo)準(zhǔn)差的數(shù)據(jù)noise_Y = np.random.normal(0,noise,torch.tensor(num_data))Y = Y + noise_Y#查看異常值是否添加if add_outlier:#計(jì)算異常值個數(shù)outlier_num = int(num_data*outlier_ratio)#查看異常值個數(shù)是都為0if outlier_num!=0:#使用torch.randint生成在num_data個數(shù)下的outlier_num個異常值的位置outlier_id = torch.randint(num_data,shape=[outlier_num])#將選出的幾個異常位置的數(shù)據(jù)進(jìn)行異常處理Y[outlier_id] = Y[outlier_id]*5return X,Yfunction:我們對上述的數(shù)據(jù)集進(jìn)行訓(xùn)練樣本和測試樣本的可視化,并對標(biāo)準(zhǔn)線進(jìn)行繪圖,從而知道我們要擬合的標(biāo)準(zhǔn)線。
import matplotlib.pyplot as plt #設(shè)置參數(shù) func = linear_func random_x = [-10,10] train_num = 100 #訓(xùn)練樣本的數(shù)目 test_num = 50 #測試樣本的數(shù)目 noise = 2 #生成訓(xùn)練集和測試集 X_train,Y_train = one_feature_data(func,random_x,num_data=train_num,noise=noise) print(X_train) print(Y_train) X_test,Y_test = one_feature_data(func,random_x,num_data=test_num,noise=noise) #生成一個大數(shù)據(jù)集 X_train_large,Y_train_large = one_feature_data(func,random_x,num_data=5000,noise=noise)#生成之前的標(biāo)準(zhǔn)線 X_underlying = torch.linspace(random_x[0],random_x[1],train_num) Y_underlying = linear_func(X_underlying) #數(shù)據(jù)的可視化 plt.scatter(X_train,Y_train,marker='*',facecolor="none",edgecolor='#e4007f',s=50,label="train_data") plt.scatter(X_test, Y_test, facecolor="none", edgecolor='#f19ec2', s=50, label="test data") plt.plot(X_underlying, Y_underlying, c='#000000', label=r"underlying distribution") plt.legend(fontsize='x-large') # 給圖像加圖例 plt.savefig('ml-vis.pdf') # 保存圖像到PDF文件中 plt.show()可視化:
1.2、模型構(gòu)建
我們根據(jù):Y=WX + b來構(gòu)建最基本的式子:
#實(shí)現(xiàn)線性模型的通式,利用張量運(yùn)算來實(shí)現(xiàn) # X: tensor, shape=[N,D] # Y: tensor, shape=[N] # w: shape=[D,1] # b: shape=[1] Y = torch.matmul(X,w)+b接下來我們嘗試創(chuàng)建一個自己的Linear類來實(shí)現(xiàn)線性回歸迭代的實(shí)現(xiàn)。
創(chuàng)建如下模型:
我們對剛建立的預(yù)測模型進(jìn)行最基本的測試,首先生成一個2行5列的隨機(jī)矩陣,然后傳入feature_size=5即5個特征的數(shù)據(jù),從而對模型進(jìn)行一次訓(xùn)練得到預(yù)測模型,然后傳入這個2行5列的矩陣從而傳入得到2個預(yù)測值。
預(yù)測結(jié)果如下:
1.3、損失函數(shù)
回歸任務(wù)是對連續(xù)值的預(yù)測,希望模型能根據(jù)數(shù)據(jù)的特征輸出一個連續(xù)值作為預(yù)測值。因此回歸任務(wù)中常用的評估指標(biāo)是均方誤差。
其中均方誤差沒有除2。
均方誤差 的定義為:
均方誤差的函數(shù)表示為:
我們采用一個簡單的樣例對該函數(shù)進(jìn)行測試,確保函數(shù)的正確性。
#構(gòu)造一個簡單的樣例對函數(shù)進(jìn)行測試 y_label = torch.tensor([[-0.2],[4.9]],dtype=torch.float64) y_predict = torch.tensor([[1.3],[2.5]],dtype=torch.float64)error = mean_squared_error(y_label,y_predict).item() print("error:",error)測試結(jié)果:
1.4、模型優(yōu)化
采用經(jīng)驗(yàn)風(fēng)險(xiǎn)最小化,線性回歸可以通過最小二乘法求出參數(shù)w和b的解析解。
最小二乘法 建立的最優(yōu)解為:
建立模型優(yōu)化器(最小二乘法)的函數(shù)如下:
1.5、模型訓(xùn)練
我們已經(jīng)建立好了模型,并且提到了損失函數(shù),也有了模型優(yōu)化器,接下來對我們已經(jīng)建立好的模型進(jìn)行求解。
#小數(shù)據(jù)集的模型訓(xùn)練 input_size = 1 model = Linear(input_size) model = optimizer_lsm(model,X_train.reshape([-1,1]),Y_train.reshape([-1,1])) print("w_pred:",model.params['w'].item(), "b_pred: ", model.params['b'].item()) #求訓(xùn)練集的誤差為 y_train_pred = model(X_train.reshape([-1,1])).squeeze() train_error = mean_squared_error(Y_train, y_train_pred).item() print("train error: ",train_error)訓(xùn)練結(jié)果:
訓(xùn)練結(jié)果:
1.6、模型評估
我們對用訓(xùn)練集訓(xùn)練過了的模型進(jìn)行測試,來表達(dá)模型的性能,測試程序如下:
#小數(shù)據(jù)集進(jìn)行評估 y_test_pred = model(X_test.reshape([-1,1])).squeeze() test_error = mean_squared_error(Y_test, y_test_pred).item() print("test error: ",test_error) #大數(shù)據(jù)集進(jìn)行評估 y_test_pred_large = model_large(X_test.reshape([-1,1])).squeeze() test_error_large = mean_squared_error(Y_test, y_test_pred_large).item() print("test error large: ",test_error_large)評估結(jié)果:
1.7、樣本數(shù)量和正則化系數(shù)的影響
(1) 調(diào)整訓(xùn)練數(shù)據(jù)的樣本數(shù)量,由 100 調(diào)整到 5000,觀察對模型性能的影響。
解: 當(dāng)樣本數(shù)量較小時,容易受到個別點(diǎn)的擾動,對于不同的數(shù)據(jù)集,實(shí)驗(yàn)結(jié)果產(chǎn)生誤差的可能性更大,模型性能較好。
當(dāng)樣本數(shù)量較大時,不容易受到個別樣本的擾動,對于不同的數(shù)據(jù)集,實(shí)驗(yàn)結(jié)果的誤差基本平衡,模型性能較好。
(2) 調(diào)整正則化系數(shù),觀察對模型性能的影響。
解: 正則化系數(shù)過大,導(dǎo)致了參數(shù)被過度正則化,特征參數(shù)趨近于0,導(dǎo)致了欠擬合。
正則化系數(shù)過小,而訓(xùn)練樣本的進(jìn)一步加大,會使參數(shù)的數(shù)目增多,導(dǎo)致模型的過擬合。
正則化系數(shù)在一定范圍內(nèi)調(diào)整時,會使模型的擬合效果編號
二、多項(xiàng)式回歸
1.1、數(shù)據(jù)集的構(gòu)建
導(dǎo)入我們所需要的一些庫:
import math import torch from matplotlib import pyplot as plt import numpy as np由于是學(xué)習(xí)多項(xiàng)式回歸,所以在此我們假設(shè)我們要擬合的非線性函數(shù)為一個縮放后的sin函數(shù)。
# sin函數(shù): sin(2 * pi * x) def sin(x):y = torch.sin(2 * math.pi * x)return y通線性回歸一樣的,我們生成數(shù)據(jù):
def one_feature_data(func, random_x, num_data, noise=0.0, add_outlier=False, outlier_ratio=0.001):"""函數(shù)功能:根據(jù)給定的函數(shù)來生成簡單的數(shù)據(jù)集輸入:- func: 函數(shù)- random_x: x的取值范圍(list)- num_data: 生成的數(shù)據(jù)集個數(shù)- noise: 添加噪聲的大小,默認(rèn)為0- add_outlier: 是否添加異常點(diǎn),默認(rèn)為False- outlier_ratio: 異常值占比輸出:- X: 特征數(shù)據(jù),shape=[num_data,1]- Y: 標(biāo)簽數(shù)據(jù),shape=[num_data,1]"""# 首先生成num_data個隨機(jī)數(shù),范圍在random_x之間X = torch.rand([num_data]) * (random_x[1] - random_x[0]) + random_x[0]# 產(chǎn)生YY = func(X)# 生成高斯分布的標(biāo)簽噪聲,使標(biāo)簽不完美。# 用np.random.normal實(shí)現(xiàn)num_data個噪聲點(diǎn),0為均值,noise標(biāo)準(zhǔn)差的數(shù)據(jù)noise_Y = torch.tensor(np.random.normal(0, noise, torch.tensor(Y.shape[0])))Y = Y + noise_Y# 查看異常值是否添加if add_outlier:# 計(jì)算異常值個數(shù)outlier_num = int(num_data * outlier_ratio)# 查看異常值個數(shù)是都為0if outlier_num != 0:# 使用torch.randint生成在num_data個數(shù)下的outlier_num個異常值的位置outlier_id = torch.randint(num_data, [outlier_num])# 將選出的幾個異常位置的數(shù)據(jù)進(jìn)行異常處理Y[outlier_id] = Y[outlier_id] * 5return X, Y# 生成數(shù)據(jù) func = sin interval = (0, 1) train_num = 15 test_num = 10 noise = 0.5 # 0.1 X_train, y_train = one_feature_data(func=func, random_x=interval, num_data=train_num, noise=noise) X_test, y_test = one_feature_data(func=func, random_x=interval, num_data=test_num, noise=noise)X_underlying = torch.linspace(interval[0], interval[1], steps=100) y_underlying = sin(X_underlying)# 繪制圖像 plt.rcParams['figure.figsize'] = (8.0, 6.0) plt.scatter(X_train, y_train, facecolor="none", edgecolor='#e4007f', s=50, label="train data") # plt.scatter(X_test, y_test, facecolor="none", edgecolor="r", s=50, label="test data") plt.plot(X_underlying, y_underlying, c='#000000', label=r"$\sin(2\pi x)$") plt.legend(fontsize='x-large') plt.savefig('ml-vis2.pdf') plt.show()我們對數(shù)據(jù)可視化,畫出標(biāo)準(zhǔn)的sinx圖,然后將訓(xùn)練樣本可視化,從而確定數(shù)據(jù)點(diǎn)在標(biāo)準(zhǔn)線上下波動:
1.2、模型構(gòu)建
我們實(shí)現(xiàn)多項(xiàng)式基函數(shù)polynomial_basis_function對原始特征x進(jìn)行轉(zhuǎn)換。
多項(xiàng)式回歸如下:
我們建立如下函數(shù)來實(shí)現(xiàn)上式:
我們首先建立輸入序列的多項(xiàng)式轉(zhuǎn)化:
轉(zhuǎn)化結(jié)果圖:
1.5、模型訓(xùn)練
轉(zhuǎn)化后的多項(xiàng)式,即變成了一特征屬性,我們可以采用線性回歸的方式來進(jìn)行訓(xùn)練。
plt.rcParams['figure.figsize'] = (12.0, 8.0)for i, degree in enumerate([0, 1, 3, 8]): # []中為多項(xiàng)式的階數(shù)model = Linear(degree)X_train_transformed = polynomial_basis_function(X_train.reshape([-1, 1]), degree)X_underlying_transformed = polynomial_basis_function(X_underlying.reshape([-1, 1]), degree)model = optimizer_lsm(model, X_train_transformed, y_train.reshape([-1, 1])) # 擬合得到參數(shù)y_underlying_pred = model(X_underlying_transformed).squeeze()print(model.params)# 繪制圖像plt.subplot(2, 2, i + 1)plt.scatter(X_train, y_train, facecolor="none", edgecolor='#e4007f', s=50, label="train data")plt.plot(X_underlying, y_underlying, c='#000000', label=r"$\sin(2\pi x)$")plt.plot(X_underlying, y_underlying_pred, c='#f19ec2', label="predicted function")plt.ylim(-2, 1.5)plt.annotate("M={}".format(degree), xy=(0.95, -1.4))# plt.legend(bbox_to_anchor=(1.05, 0.64), loc=2, borderaxespad=0.) plt.legend(loc='lower left', fontsize='x-large') plt.savefig('ml-vis3.pdf') plt.show()1.6、模型評估
通過均方誤差來衡量訓(xùn)練誤差、測試誤差以及在沒有噪音的加入下sin函數(shù)值與多項(xiàng)式回歸值之間的誤差,更加真實(shí)地反映擬合結(jié)果。多項(xiàng)式分布階數(shù)從0到8進(jìn)行遍歷。
# 訓(xùn)練誤差和測試誤差 training_errors = [] test_errors = [] distribution_errors = []# 遍歷多項(xiàng)式階數(shù) for i in range(9):model = Linear(i)X_train_transformed = polynomial_basis_function(X_train.reshape([-1, 1]), i)X_test_transformed = polynomial_basis_function(X_test.reshape([-1, 1]), i)X_underlying_transformed = polynomial_basis_function(X_underlying.reshape([-1, 1]), i)optimizer_lsm(model, X_train_transformed, y_train.reshape([-1, 1]))y_train_pred = model(X_train_transformed).squeeze()y_test_pred = model(X_test_transformed).squeeze()y_underlying_pred = model(X_underlying_transformed).squeeze()train_mse = mean_squared_error(y_train, y_train_pred).item()training_errors.append(train_mse)test_mse = mean_squared_error(y_test, y_test_pred).item()test_errors.append(test_mse)# distribution_mse = mean_squared_error(y_true=y_underlying, y_pred=y_underlying_pred).item()# distribution_errors.append(distribution_mse)print("train errors: \n", training_errors) print("test errors: \n", test_errors) # print ("distribution errors: \n", distribution_errors)# 繪制圖片 plt.rcParams['figure.figsize'] = (8.0, 6.0) plt.plot(training_errors, '-.', mfc="none", mec='#e4007f', ms=10, c='#e4007f', label="Training") plt.plot(test_errors, '--', mfc="none", mec='#f19ec2', ms=10, c='#f19ec2', label="Test") # plt.plot(distribution_errors, '-', mfc="none", mec="#3D3D3F", ms=10, c="#3D3D3F", label="Distribution") plt.legend(fontsize='x-large') plt.xlabel("degree") plt.ylabel("MSE") plt.savefig('ml-mse-error.pdf') plt.show()評估結(jié)果:
通過觀察可視化結(jié)果,我們可以得到:
對于模型過擬合的情況,可以引入正則化方法,通過向誤差函數(shù)中添加一個懲罰項(xiàng)來避免系數(shù)傾向于較大的取值。
代碼如下:
評估結(jié)果:
三、嘗試封裝Runner類
Runner類的成員函數(shù)定義如下:
- __init__函數(shù):實(shí)例化Runner類,需要傳入模型、損失函數(shù)、優(yōu)化器和評價(jià)指標(biāo)等;
- train函數(shù):模型訓(xùn)練,指定模型訓(xùn)練需要的訓(xùn)練集和驗(yàn)證集;
- evaluate函數(shù):通過對訓(xùn)練好的模型進(jìn)行評價(jià),在驗(yàn)證集或測試集上查看模型訓(xùn)練效果;
- predict函數(shù):選取一條數(shù)據(jù)對訓(xùn)練好的模型進(jìn)行預(yù)測;
- save_model函數(shù):模型在訓(xùn)練過程和訓(xùn)練結(jié)束后需要進(jìn)行保存;
- load_model函數(shù):調(diào)用加載之前保存的模型。
包裝Runner類示意圖:
包裝后的Runner類:
class Runner():def __init__(self,model,model_loss,model_optimizer,model_evaluate):self.model = modelself.model_loss = model_lossself.model_optimizer = model_optimizerself.model_evaluate = model_evaluatedef train(self,Train_feature,Test_feature,**kwargs):self.Train_feature = Train_featurepassreturn #各個參數(shù)def evaluate(self,label,**kwargs):loss = self.model_loss(label,self.predict(self.Train_feature))# accuracy =passreturn #返回精度和誤差def predict(self,X,**kwargs):#用train 的各個參數(shù)來對輸入序列X進(jìn)行預(yù)測,返回預(yù)測值passreturn #返回預(yù)測值def save_model(self,save_path):passdef load_model(self,model_path):pass四、基于線性回歸的波士頓房價(jià)預(yù)測
4.1數(shù)據(jù)集介紹
預(yù)覽一下我們的數(shù)據(jù)集的前五條數(shù)據(jù),看看有沒有問題。
預(yù)覽圖:
4.2數(shù)據(jù)清洗
4.2.1缺失值分析
用isna().sum()各個屬性的統(tǒng)計(jì)缺失值個數(shù)。
data.isna().sum()分析下圖,說明此數(shù)據(jù)集不存在數(shù)據(jù)缺失的情況。
4.2.2異常值處理
通過箱線圖直觀的顯示數(shù)據(jù)分布,并觀測數(shù)據(jù)中的異常值。箱線圖一般由五個統(tǒng)計(jì)值組成:最大值、上四分位、中位數(shù)、下四分位和最小值。一般來說,觀測到的數(shù)據(jù)大于最大估計(jì)值或者小于最小估計(jì)值則判斷為異常值,其中:
箱線圖介紹:
查看數(shù)據(jù)集各個屬性的異常值并可視化的代碼:
import matplotlib.pyplot as plt # 可視化工具 import pandas as pd # 開源數(shù)據(jù)分析和操作工具# 利用pandas加載波士頓房價(jià)的數(shù)據(jù)集 data=pd.read_csv("C:\\boston_house_prices.csv") # 預(yù)覽前5行數(shù)據(jù) data.head() # 查看各字段缺失值統(tǒng)計(jì)情況 data.isna().sum() # 箱線圖查看異常值分布 def boxplot(data, fig_name):# 繪制每個屬性的箱線圖data_col = list(data.columns)# 連續(xù)畫幾個圖片plt.figure(figsize=(5, 5), dpi=300)# 子圖調(diào)整plt.subplots_adjust(wspace=0.6)# 每個特征畫一個箱線圖for i, col_name in enumerate(data_col):plt.subplot(3, 5, i + 1)# 畫箱線圖plt.boxplot(data[col_name],showmeans=True,meanprops={"markersize": 1, "marker": "D", "markeredgecolor": "#C54680"}, # 均值的屬性medianprops={"color": "#946279"}, # 中位數(shù)線的屬性whiskerprops={"color": "#8E004D", "linewidth": 0.4, 'linestyle': "--"},flierprops={"markersize": 0.4},)# 圖名plt.title(col_name, fontdict={"size": 5}, pad=2)# y方向刻度plt.yticks(fontsize=4, rotation=90)plt.tick_params(pad=0.5)# x方向刻度plt.xticks([])plt.savefig(fig_name)plt.show()boxplot(data, 'ml-vis5.pdf')可視化結(jié)果:
由圖可以直觀的看出,數(shù)據(jù)中存在很多的異常值,即超出上下兩條杠的部分中的黑圓圈,我們將這些異常值認(rèn)為是數(shù)據(jù)集中的“噪聲”,并將臨界值取代噪聲點(diǎn),從而完成對數(shù)據(jù)集異常值的處理。
替換代碼:
取代后的箱線圖:
4.3數(shù)據(jù)集的劃分
將數(shù)據(jù)集劃分為兩份:訓(xùn)練集和測試集,不包括驗(yàn)證集。
使用下邊的代碼進(jìn)行劃分:
4.4特征工程
為了消除綱量對數(shù)據(jù)特征之間影響,在模型訓(xùn)練前,需要對特征數(shù)據(jù)進(jìn)行歸一化處理,將數(shù)據(jù)縮放到[0, 1]區(qū)間內(nèi),使得不同特征之間具有可比性。
import torchX_train = torch.tensor(X_train,dtype=torch.float32) X_test = torch.tensor(X_test,dtype=torch.float32) y_train = torch.tensor(y_train,dtype=torch.float32) y_test = torch.tensor(y_test,dtype=torch.float32) X_min = torch.min(X_train,dim=0) X_max = torch.max(X_train,dim=0) X_train = (X_train-X_min.values)/(X_max.values - X_min.values)X_test = (X_test-X_min.values)/(X_max.values - X_min.values)# 訓(xùn)練集構(gòu)造 train_dataset=(X_train,y_train) # 測試集構(gòu)造 test_dataset=(X_test,y_test)4.5模型構(gòu)建
首先,實(shí)例化一個對象。
關(guān)于nndl,我們可以不用這個包,可以用我們上邊自己寫的Linear類,從而進(jìn)行一樣的操作,也能得到結(jié)果。
4.6完善Runner類
我們將之前只有一個外殼的Runner類補(bǔ)充,首先:
import torch.nn as nn mse_loss = nn.MSELoss()完整實(shí)現(xiàn)如下:
import torch.nn as nn import torch import os from nndl.op import Linear from nndl.opitimizer import optimizer_lsm # 模型實(shí)例化 input_size = 12 model=Linear(input_size) mse_loss = nn.MSELoss()class Runner(object):def __init__(self, model, optimizer, loss_fn, metric):# 優(yōu)化器和損失函數(shù)為None,不再關(guān)注# 模型self.model = model# 評估指標(biāo)self.metric = metric# 優(yōu)化器self.optimizer = optimizerdef train(self, dataset, reg_lambda, model_dir):X, y = datasetself.optimizer(self.model, X, y, reg_lambda)# 保存模型self.save_model(model_dir)def evaluate(self, dataset, **kwargs):X, y = datasety_pred = self.model(X)result = self.metric(y_pred, y)return resultdef predict(self, X, **kwargs):return self.model(X)def save_model(self, model_dir):if not os.path.exists(model_dir):os.makedirs(model_dir)params_saved_path = os.path.join(model_dir, 'params.pdtensor')torch.save(model.params, params_saved_path)def load_model(self, model_dir):params_saved_path = os.path.join(model_dir, 'params.pdtensor')self.model.params = torch.load(params_saved_path)optimizer = optimizer_lsm runner = Runner(model, optimizer=optimizer,loss_fn=None, metric=mse_loss)4.7模型訓(xùn)練
訓(xùn)練代碼:
optimizer = optimizer_lsm runner = Runner(model, optimizer=optimizer,loss_fn=None, metric=mse_loss)# 模型保存文件夾 saved_dir = 'D:/models_'# 啟動訓(xùn)練 runner.train(train_dataset,reg_lambda=0,model_dir=saved_dir) columns_list = data.columns.to_list() weights = runner.model.params['w'].tolist() b = runner.model.params['b'].item()for i in range(len(weights)):print(columns_list[i],"weight:",weights[i])print("b:",b)訓(xùn)練結(jié)果:
加載訓(xùn)練好的模型參數(shù),在測試集上得到模型的MSE指標(biāo)。
4.8 模型預(yù)測
預(yù)測代碼
runner.load_model(saved_dir) pred = runner.predict(X_test[:1]) print("真實(shí)房價(jià):",y_test[:1].item()) print("預(yù)測的房價(jià):",pred.item())預(yù)測結(jié)果:
從輸出結(jié)果看,預(yù)測房價(jià)接近真實(shí)房價(jià)。
后話:一些問題
- 問題1:使用類實(shí)現(xiàn)機(jī)器學(xué)習(xí)模型的基本要素有什么優(yōu)點(diǎn)?
解: 我自我感覺使用類實(shí)現(xiàn)機(jī)器學(xué)習(xí)模型的基本要素,可以讓我們以后對任何一個適用于該樣本的數(shù)據(jù)集能夠以更簡單的形式進(jìn)行訓(xùn)練,優(yōu)化了后續(xù)的訓(xùn)練代碼,并且以類封裝函數(shù)可以讓整體更加清晰,思路更加清楚,同時對于機(jī)器學(xué)習(xí)模型的整體把握也會好很多。 - 問題2:算子op、優(yōu)化器opitimizer放在單獨(dú)的文件中,主程序在使用時調(diào)用該文件。這樣做有什么優(yōu)點(diǎn)?
解: 能夠簡化操作,直接使用import引用文件,不需要再重新寫這些算子和優(yōu)化器,從而不需要再進(jìn)行更多的代碼編寫,省時省力。 - 問題3:線性回歸通常使用平方損失函數(shù),能否使用交叉熵?fù)p失函數(shù)?為什么?
解: 如果要問為什么線性回歸要使用均方誤差,可以參考這篇博客:【線性回歸:為什么損失函數(shù)要使用均方誤差】,交叉熵?fù)p失的假設(shè)是誤差分布是二值分布,因此更適用于分類等離散屬性的問題,而均方誤差則假設(shè)數(shù)據(jù)的分布是正態(tài)分布,更加是用于連續(xù)屬性的誤差分析。
參考以下博客:
NNDL 實(shí)驗(yàn)三 線性回歸
神經(jīng)網(wǎng)絡(luò)與深度學(xué)習(xí):案例與實(shí)踐
平方損失函數(shù)與交叉熵?fù)p失函數(shù) & 回歸問題為何不使用交叉熵?fù)p失函數(shù)
總結(jié)
以上是生活随笔為你收集整理的【线性回归——从简单构建到实现数据预测】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 给ChatGLM2注入知识;阅文集团发布
- 下一篇: 博主有喜:拿了金奖和最佳创新奖