日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人工智能 > 循环神经网络 >内容正文

循环神经网络

循环神经网络RNN

發布時間:2024/9/27 循环神经网络 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 循环神经网络RNN 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.46.循環神經網絡RNN

RNN是Recurrent Neural Networks的縮寫,即循環神經網絡,它常用于解決序列問題。RNN有記憶功能,除了當前輸入,還把上下文環境作為預測的依據。它常用于語音識別、翻譯等場景之中。

RNN是序列模型的基礎,盡管能夠直接調用現成的RNN算法,但后續的復雜網絡很多構建在RNN網絡的基礎之上,如Attention方法需要使用RNN的隱藏層數據。RNN的原理并不復雜,但由于其中包括循環,很難用語言或者畫圖來描述,最好的方法是自己手動編寫一個RNN網絡。本篇將介紹RNN網絡的原理及具體實現。

1.46.1.序列

在學習循環神經網絡之前,先看看什么是序列。序列sequence簡稱seq,是有先后順序的一組數據。自然語言處理是最為典型的序列問題,比如將一句話翻譯成另一句話時,其中某個詞匯的含義不僅取決于它本身,還與它前后的多個單詞相關。類似的,如果想預測電影的情節發展,不僅與當前的畫面有關,還與當前的一系列前情有關。在使用序列模型預測的過程中,輸入是序列,而輸出是一個或多個預測值。

在使用深度學習模型解決序列問題時,最容易混淆的是,序列與序列中的元素。在不同的場景中,定義序列的方式不同,當分析單詞的感情色彩時,一個單詞是一個序列seq;當分析句子感情色彩時,一個句子是一個seq,其中的每個單詞是序列中的元素;當分析文章感情色彩時,一篇文章是一個seq。簡單地說,seq是最終使用模型時的輸入數據,由一系列元素組成。

當分析句子的感情色彩時,以句為seq,而句中包含的各個單詞的含義,以及單詞間的關系是具體分析的對象,此時,單詞是序列中的元素,每一個單詞又可有多維特征。從單詞中提取特征的方法將在后面的自然語言處理中介紹。

循環神經網絡

RNN有很多種形式,單個輸入單個輸出;多個輸入多個輸出,單個輸入多個輸出等等。

舉個最簡單的例子:用模型預測一個四字短語的感情色彩,它的輸入為四個元素X={x1,x2,x3,x4},它的輸出為單個值Y={y1}。字的排列順序至關重要,比如“從好變壞”和“從壞變好”,表達的意思完全相反。之所以輸入輸出的個數不需要一一對應,是因為中間的隱藏層,變向存儲中間信息。

如果把模型設想成黑盒,如下圖所示:

如果模型使用全連接網絡,在每次迭代時,模型將計算各個元素x1,x2…中各個特征f1,f2…代入網絡,求它們對結果y的貢獻度。

RNN網絡則要復雜一些,在模型內部,它不是將序列中所有元素的特征一次性輸入模型,而是每一次將序列中單個元素的特征輸入模型,下圖描述了RNN的數據處理過程,左圖為分布展示,右圖將所有時序步驟抽象成單一模塊。

第一步:將第一個元素x1的特征f1,f2…輸入模型,模型根據輸入計算出隱藏層h。

第二步:將第二個元素x2的特征輸入模型,模型根據輸入和上一步產生的h再計算隱藏層h,其它元素以此類推。

第三步:將最后一個元素xn的特征輸入模型,模型根據輸入和上一步產生的h計算隱藏層h和預測值y。

隱藏層h可視為將序列中前面元素的特征和位置通過編碼向前傳遞,從而對輸出y發生作用,隱藏層的大小決定了模型攜帶信息量的多少。隱藏層也可以作為模型的輸入從外部傳入,以及作為模型的輸出返回給外部調用。

1.46.2.代碼分析

本例仍使用上篇中的航空乘客序列數據,分別用兩種方法實現RNN:自己編寫程序實現RNN模型,以及調用Pytorch提供的RNN模型。前一種方法主要用于剖析原理,后一種用于展示常用的調用方法。

1.46.2.1.讀取數據

首先導入頭文件,讀取乘客數據,做歸一化處理,并將數據切分為測試集和訓練集,與之前不同的是加入了create_dataset函數,用于生成序列數據,序列的輸入部分,每個元素中包括兩個特征:前一個月的乘客量prev和月份值mon,這里的月份值并不是關鍵特征,主要用于在例程中展示如何使用多個特征。

# -*- coding: UTF-8 -*-import pandas as pd import numpy as np import matplotlib.pyplot as pltimport torch import torch.nn as nn from torch.autograd import Variable# 歸一化 def feature_normalize(data):mu = np.mean(data, axis=0)std = np.std(data, axis=0)return (data - mu) / std# 數據轉換 def create_dataset(df):dataX = torch.from_numpy(np.array(df[['prev', 'mon']].astype('float32')).reshape(-1, 1, 2))dataY = torch.from_numpy(np.array(df['y'].astype('float32')).reshape(-1, 1, 1))return dataX, dataYdf = pd.read_csv('data/AirPassengers.csv') df['y'] = feature_normalize(df['#Passengers']) df['mon'] = feature_normalize(df['Month'].apply(lambda x: float(x[5:]))) df['prev'] = df['y'].shift() # 將前一個月的乘客量寫入prev特征 df = df.dropna() # 去掉包含空值的行TRAIN_PERCENT = 0.7 train_size = int(len(df) * TRAIN_PERCENT) train = df[:train_size]

1.46.2.2.實現RNN模型

第一步:實現模型類,此例中的RNN模型除了全連接層,還生成了一個隱藏層,并在下一次前向傳播時將隱藏層輸出的數據與輸入數據組合后再代入模型運算。

# -*- coding: UTF-8 -*-import pandas as pd import numpy as np import matplotlib.pyplot as pltimport torch import torch.nn as nn from torch.autograd import Variable# 歸一化 def feature_normalize(data):mu = np.mean(data, axis=0)std = np.std(data, axis=0)return (data - mu) / std# 數據轉換 def create_dataset(df):dataX = torch.from_numpy(np.array(df[['prev', 'mon']].astype('float32')).reshape(-1, 1, 2))dataY = torch.from_numpy(np.array(df['y'].astype('float32')).reshape(-1, 1, 1))return dataX, dataYdf = pd.read_csv('data/AirPassengers.csv') df['y'] = feature_normalize(df['#Passengers']) df['mon'] = feature_normalize(df['Month'].apply(lambda x: float(x[5:]))) df['prev'] = df['y'].shift() # 將前一個月的乘客量寫入prev特征 df = df.dropna() # 去掉包含空值的行TRAIN_PERCENT = 0.7 train_size = int(len(df) * TRAIN_PERCENT) train = df[:train_size]

第二步,訓練模型,使用全部數據訓練500次,在每次訓練時,內部for循環將序列中的每個元素代入模型,并將模型輸出的隱藏層和下一個元素一起送入下一次迭代。

FEATURE_SIZE = 2 OUTPUT_SIZE = 1 model = RNN1(FEATURE_SIZE, 128, OUTPUT_SIZE) loss_func = nn.MSELoss() # 損失函數 optimizer = torch.optim.Adam(model.parameters(), lr=0.01) # 優化器 train_x, train_y = create_dataset(train) all_x, all_y = create_dataset(df)for e in range(500):h_state = model.initHidden()for i, (x, y) in enumerate(zip(train_x, train_y)):prediction, _h_state = model(x, h_state) # 返回隱藏層h_state = _h_state.data # 隱藏層的參數部分loss = loss_func(prediction, y)optimizer.zero_grad()loss.backward()optimizer.step()

第三步:預測和作圖,預測的過程與訓練一樣,把全部數據拆分成元素代入模型,并將每一次預測結果存儲在數組中,并作圖顯示。

model = model.eval() arr_pred = [] h_state = model.initHidden() for x, y in zip(all_x, all_y):prediction, _h_state = model(x, h_state) # 返回隱藏層h_state = _h_state.dataarr_pred.append(prediction.detach().numpy().flatten()[0]) plt.plot(all_y.numpy().flatten(), 'y', label='real') plt.plot(arr_pred, label='prediction', alpha=0.5) plt.legend(loc='best') plt.grid() plt.show()

需要注意的是,在訓練和預測過程中,每一次開始輸入新序列之前,都重置了隱藏層,這是由于隱藏層的內容只與當前序列相關,序列之間并無連續性。

程序輸出結果如下圖所示:

1.46.2.3.調用現有RNN模型

使用Pytorch提供的RNN模型,torch.nn.RNN類可直接使用,是循環網絡最常用的解決方案。RNN,LSTM,GRU等循環網絡都實現在同一源碼文件torch/nn/modules/rnn.py中。

第一步:創建模型,模型包含兩部分,第一部分是Pytorch提供的RNN層,第二部分是一個全連接層,用于將RNN的輸出轉換成輸出目標的維度。

# -*- coding: UTF-8 -*-import torch import torch.nn as nnclass RNN2(nn.Module):def __init__(self, input_size, hidden_size, output_size=1, num_layers=2):super(RNN2, self).__init__()self.rnn = nn.RNN(input_size, hidden_size, num_layers)self.reg = nn.Linear(hidden_size, output_size)def forward(self, x):x, _ = self.rnn(x) # 未在不同序列中傳遞hidden_statereturn self.reg(x)

Pytorch的RNN前向傳播允許將隱藏層數據h作為參數傳入模型,并將模型產生的h和y作為函數返回值。形如: pred, h_state = model(x, h_state)

什么情況下需要接收隱藏層的狀態h_state,并轉入下一次迭代呢?當處理單個seq時,h在內部前向傳遞;當序列與序列之間也存在前后依賴關系時,可以接收h_state并傳入下一步迭代。另外,當模型比較復雜如LSTM模型包含眾多參數,傳遞會增加模型的復雜度,使訓練過程變慢。本例未將隱藏層轉到模型外部,這是由于模型內部實現了對整個序列的處理,而非處理單個元素,而每次代入的序列之間又沒有連續性。

第二步:訓練模型,與上例中把序列中的元素逐個代入模型不同,本例一次性把整個序列代入了模型,因此,只有一個for循環。

FEATURE_SIZE = 2 OUTPUT_SIZE = 1 model = RNN2(FEATURE_SIZE, 64, OUTPUT_SIZE) loss_func = nn.MSELoss() optimizer = torch.optim.Adam(model.parameters(), lr=0.01) train_x, train_y = create_dataset(train) all_x, all_y = create_dataset(df) # 全部數據for e in range(500):var_x = Variable(train_x)var_y = Variable(train_y)out = model(var_x) # var_x: [100, 1, 2]loss = loss_func(out, var_y)optimizer.zero_grad()loss.backward()optimizer.step()if (e+1)%100==0:print('Epoch:{}, Loss:{:.5f}'.format(e+1, loss.item()))

Pythorch支持批量處理,前向傳遞時輸入數據格式是[seq_len, batch_size, input_dim),本例中輸入數據的維度是[100, 1, 2],input_dim是每個元素的特征數,batch_size是訓練的序列個數,seq_len是序列的長度,這里使用70%作為訓練數據,seq_len為100。如果數據維度的順序與要求不一致,一般使用transpose轉換。

第三步:預測和作圖,將全部數據作為序列代入模型,并用預測值作圖。

model = model.eval() pred_y = model(Variable(all_x)) # 預測 plt.plot(all_y.view(-1).data.numpy(), 'y', label='real') plt.plot(pred_y.view(-1).data.numpy(), label='prediction', alpha=0.5) plt.legend(loc='best') plt.grid() plt.show()

程序輸出結果如下圖所示:

可以看到,經過500次迭代,在前100個元素的訓練集上擬合得很好,但在測試集效果較差,可能存在過擬合。

總結

以上是生活随笔為你收集整理的循环神经网络RNN的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。