深度学习修炼(五)——基于pytorch神经网络模型进行气温预测
文章目錄
- 5 基于pytorch神經網絡模型進行氣溫預測
- 5.1 實現前的知識補充
- 5.1.1 神經網絡的表示
- 5.1.2 隱藏層
- 5.1.3 線性模型出錯
- 5.1.4 在網絡中加入隱藏層
- 5.1.5 激活函數
- 5.1.6 小批量隨機梯度下降
- 5.2 實現的過程
- 5.2.1 預處理
- 5.2.2 搭建網絡模型
- 5.3 簡化實現
- 5.4 評估模型
5 基于pytorch神經網絡模型進行氣溫預測
在前面的學習中,我們已經有了一個大概的思路,但是,線性模型畢竟十分簡單,我們需要再搭建一個強化自己的知識點。
在這節課中,我們將會用到以下的數據集,請點擊自主下載。
temps.zip - 氣溫預測數據集下載
感謝我吧!C站上面有那么多的付費資源,而我自掏腰包買了這個資源無償分享。
5.1 實現前的知識補充
我們不同于前面的線性模型神經網絡,我們在下面的小節中打算搭建的是一個多層感知機。
5.1.1 神經網絡的表示
多層感知機是啥?讓我們來看看線性回歸的神經網絡先。
在之前的學習中,線性回歸可以多參數,最終輸出只有一個。但是在多層感知機中,它的模型架構確是這樣:
以上的圖是一個神經網絡的圖片,讓我們給這個圖片的不同部分取些名字。
我們由輸入特征x1,x2...xnx_1,x_2...x_nx1?,x2?...xn?,它們被豎直地堆疊起來,這叫做神經網絡的輸入層。但是前面我們也說過,這一層只提供輸入特征,計算不在這一層,所以一般輸入層是不算入神經網絡的層數的。然后這里還有另外一層我們稱之為隱藏層;而在最后一層是輸出層,他負責產生預測值。
5.1.2 隱藏層
在訓練集中,當通過神經網絡的時候,隱藏層計算的值我們是不知道的,也就是說我們看不見它們在訓練集中具有的值。當然你要是真想知道里面的值是啥,你可以從輸入層開始根據隱藏層對應的算法一步一步算進去。
5.1.3 線性模型出錯
雖然我們前面一直在用線性回歸模型,但是并不代表我們能一直用下去。因為線性意味著自變量和因變量呈單調趨勢。也就是說:特征變大模型輸出就變大,特征變小輸出就變小。
5.1.4 在網絡中加入隱藏層
我們可以通過在網絡中加入一個或多個隱藏層來克服線性模型的限制, 使其能處理更普遍的函數關系類型。 要做到這一點,最簡單的方法是將許多全連接層堆疊在一起。 每一層都輸出到上面的層,直到生成最后的輸出。 我們可以把前L?1層看作表示,把最后一層看作線性預測器。 這種架構通常稱為多層感知機(multilayer perceptron),通常縮寫為MLP。 下面,我們以圖的方式描述了多層感知機。
5.1.5 激活函數
這里我們暫時不細講激活函數,但是你需要知道的點是,在使用神經網絡時,為了方式其輸出單調,我們需要在隱藏層和輸出層中使用激活函數,從而將輸出結果投射到某個區間上。
激活函數有多種,如ReLU(修正線性單元)及其變體、sigmoid函數、tanh函數等。如果輸出是0、1值(二分類問題),則輸入層選擇sigmoid函數,然后其它的所有單元都選擇ReLU函數。這是很多激活函數的默認選擇,如果在隱藏層上不確定用哪個激活函數,那么通常會使用ReLU激活函數。
5.1.6 小批量隨機梯度下降
在前面機器學習中,我們曾經提到優化損失函數的方法是用梯度下降(gradient descent)的方法,這種方法幾乎可以用來優化所有深度學習模型,他通過不斷地在損失函數遞減的方向上更新參數來降低誤差。
梯度下降最簡單的用法是計算損失函數關于模型參數的導數。但實際上執行可能會非常慢,因為每一次更新參數,我們基本遍歷每個樣本。一次,我們通常會在每次更新的時候抽取一小批樣本,這種方法的變體我們叫做小批量隨機梯度下降。如下面所示:
(w,b)<?(w,b)?η∣B∣∑i∈B?(w,b)l(i)(w,b)(w,b)<-(w,b)-\frac{η}{|B|} \sum _{i∈B}?_{(w,b)}l^{(i)}(w,b)(w,b)<?(w,b)?∣B∣η?∑i∈B??(w,b)?l(i)(w,b)
我們現在從所有的樣本中抽取了BBB個樣本,也就是小批量BBB。參數η我們叫做學習率。
5.2 實現的過程
5.2.1 預處理
在實現前,我們先導入所需的包。
import pandas as pd import numpy as np import torch import matplotlib.pyplot as plt我們把提前下載好的數據集加載進去,并且查看前五行以及特征,方便后續處理。
features = pd.read_csv('temps.csv')# 查看數據前五行 features.head()out:
數據說明
- temp_2:前天的最高溫度值
- temp_1:昨天的最高溫度值
- average:在歷史中,每年這一天的平均最高溫度值
- actual:標簽值,當天的真實最高溫度
- friend:朋友預測的可能值
讓我們查看數據有多少,即查看維度:
# 查看數據的維度 print('數據維度:',features.shape)out:
數據維度: (348, 9)
我們注意到這里有很多關于時間的特征,我們將其處理為時間序列。如果你這里不是很懂,照做即可。
# 將時間轉換為時間序列 import datetime# 分別得到年、月、日 years = features['year'] months = features['month'] days = features['day']# datetime格式 dates = [str(int(year))+'-'+str(int(month))+'-'+str(int(day)) for year,month,day in zip(years,months,days)] dates = [datetime.datetime.strptime(date,'%Y-%m-%d') for date in dates]打印結果看看!
dates[:5]out:
[datetime.datetime(2016, 1, 1, 0, 0),
datetime.datetime(2016, 1, 2, 0, 0),
datetime.datetime(2016, 1, 3, 0, 0),
datetime.datetime(2016, 1, 4, 0, 0),
datetime.datetime(2016, 1, 5, 0, 0)]
除此之外,我們還注意到數據中的week特征為字符串,字符串可不能處理,我們必須將其轉換為可處理的類型,根據前面所講的知識點,我們將其轉換為獨熱編碼。
# 將week轉為獨熱編碼 features = pd.get_dummies(features) features.head(5)out:
我們是要預測當天的氣溫,所以我們應該把actual看做標簽項,提取出來。
# 分離y_train labels = np.array(features['actual'])# 在特征中去掉y_train features = features.drop('actual',axis = 1)# 名字單獨保存一下,以備后患 feature_list = list(features.columns)# 轉換成合適的格式 features = np.array(features)查看一下訓練集的大小:
features.shapeout:
(348, 14)
再次觀察數據,有些特征的數據數值很大有些則很小,我們需要做標準化。從機器學習的學習得知,我們可以利用sklearn的庫來進行標準化。
#有些數值大有些數值小,做標準化 from sklearn import preprocessing input_features = preprocessing.StandardScaler().fit_transform(features)5.2.2 搭建網絡模型
首先我們需要將輸出到網絡模型中的數據轉換為網絡能接受的張量格式。
# 將array轉為張量 x = torch.tensor(input_features,dtype = float) y = torch.tensor(labels,dtype = float)我們打算搭建具有一個隱藏層的多層感知機,為此,我們設定兩個線性模型及參數,并且隨機初始化它們。觀察訓練集的特征為14,所以輸出層的w必須是(14,m),其中m我隨意指定為128,意為將14個輸入特征轉化為隱藏層的128個隱藏特征。由矩陣相乘知識可以得出的是348×128的矩陣,所以我們的biases指定為(128×1)。隱藏層同理。
# 權重參數初始化 weights = torch.randn((14,128),dtype = float,requires_grad = True) biases = torch.randn(128,dtype = float,requires_grad = True) weights2 = torch.randn((128,1),dtype = float,requires_grad = True) biases2 = torch.randn(1,dtype = float,requires_grad = True)我們還要指定學習率和存放每次計算所得損失的列表。
learning_rate = 0.001 losses = []做完上述工作,我們開始對網絡模型進行梯度下降。
# 指定梯度下降次數1000次 for i in range(1000):# 計算隱藏層-線性模型hidden = x.mm(weights) + biases# 加入激活函數-加入激活函數hidden = torch.relu(hidden)# 預測結果計算-輸出值predictions = hidden.mm(weights2) + biases2# 計算損失-平方損失函數loss = torch.mean((predictions - y) ** 2)# 將每次的損失轉為numpy格式并添加到損失列表中losses.append(loss.data.numpy())# 打印損失值if i % 100 == 0:print('loss:',loss)# 反向傳播計算loss.backward()# 更新參數weights.data.add_(- learning_rate * weights.grad.data)biases.data.add_(- learning_rate * biases.grad.data)weights2.data.add_(- learning_rate * weights2.grad.data)biases2.data.add_(- learning_rate * biases2.grad.data)# 每次迭代后清空梯度weights.grad.data.zero_()biases.grad.data.zero_()weights2.grad.data.zero_()biases2.grad.data.zero_()out:
loss: tensor(6845.0772, dtype=torch.float64, grad_fn=)
loss: tensor(155.3488, dtype=torch.float64, grad_fn=)
loss: tensor(147.4410, dtype=torch.float64, grad_fn=)
loss: tensor(145.0307, dtype=torch.float64, grad_fn=)
loss: tensor(143.6870, dtype=torch.float64, grad_fn=)
loss: tensor(142.8334, dtype=torch.float64, grad_fn=)
loss: tensor(142.2421, dtype=torch.float64, grad_fn=)
loss: tensor(141.7909, dtype=torch.float64, grad_fn=)
loss: tensor(141.4391, dtype=torch.float64, grad_fn=)
loss: tensor(141.1529, dtype=torch.float64, grad_fn=)
至此,訓練模型完畢。以上就是一個簡單的網絡模型搭建過程。
5.3 簡化實現
我們前面“基本上”是從零搭建了神經網絡模型。而事實上,torch為我們提供了豐富的API幫我們實現神經網絡,我們試著再一次實現。
# 指定規模 input_size = input_features.shape[1] hidden_size = 128 output_size = 1 batch_size = 16# 搭建網絡 my_nn = torch.nn.Sequential(torch.nn.Linear(input_size,hidden_size),torch.nn.Sigmoid(),torch.nn.Linear(hidden_size,output_size), )# 定義損失函數 cost = torch.nn.MSELoss(reduction = 'mean') optimizer = torch.optim.Adam(my_nn.parameters(),lr = 0.001) # 訓練網絡 losses = [] for i in range(1000):batch_loss = []# 小批量隨機梯度下降進行訓練for start in range(0,len(input_features),batch_size):end = start+batch_size if start + batch_size < len(input_features) else len(input_features)xx = torch.tensor(input_features[start:end],dtype = torch.float,requires_grad = True)yy = torch.tensor(labels[start:end],dtype = torch.float,requires_grad = True)prediction = my_nn(xx)loss = cost(prediction,yy)optimizer.zero_grad()loss.backward(retain_graph=True)optimizer.step()batch_loss.append(loss.data.numpy())# 打印損失# 打印損失值if i % 100 == 0:losses.append(np.mean(batch_loss))print(i,np.mean(batch_loss))out:
0 3984.4104
100 37.5414
200 35.608612
300 35.26231
400 35.09969
500 34.969772
600 34.853214
700 34.73715
800 34.61541
900 34.48683
5.4 評估模型
我們可以嘗試用下面的代碼去評估,代碼較復雜,復制下去跑出看看效果即可。
x = torch.tensor(input_features,dtype = torch.float) predict = my_nn(x).data.numpy()# 轉換日期格式 dates = [str(int(year))+'-'+str(int(month))+'-'+str(int(day)) for year,month,day in zip(years,months,days)] dates = [datetime.datetime.strptime(date,'%Y-%m-%d') for date in dates]# 創建一個表格來存日期和其對應的標簽數值 true_data = pd.DataFrame(data = {'date':dates,'actual':labels})# 同理,在創建一個來存日期和其對應的模型預測值 mouths = features[:,feature_list.index('month')] days = features[:,feature_list.index('day')] years = features[:,feature_list.index('year')]test_dates = [str(int(year))+'-'+str(int(month))+'-'+str(int(day)) for year,month,day in zip(years,months,days)] test_dates = [datetime.datetime.strptime(date,'%Y-%m-%d') for date in test_dates]predictions_data = pd.DataFrame(data = {'date':test_dates,'prediction':predict.reshape(-1)})# 真實值 plt.plot(true_data['date'],true_data['actual'],'b-',label = 'actual')# 預測值 plt.plot(predictions_data['date'],predictions_data['prediction'],'ro',label = 'prediction') plt.xticks(rotation = '60') plt.legend()# 圖名 plt.xlabel('Date');plt.ylabel('Maximum Temperature (F)');plt.title('Actual and Predicted Values')plt.show()out:
看得出來,我們的模型擬合能力效果還是不錯的。
總結
以上是生活随笔為你收集整理的深度学习修炼(五)——基于pytorch神经网络模型进行气温预测的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 字符串表达式求值 C#实现
- 下一篇: Redhat Linux编译安装LAMP