網(wǎng)站建設見站分析和準備論文網(wǎng)站seo優(yōu)化網(wǎng)站
經(jīng)典的全連接神經(jīng)網(wǎng)絡
經(jīng)典的全連接神經(jīng)網(wǎng)絡來包含四層網(wǎng)絡:輸入層、兩個隱含層和輸出層,將手寫數(shù)字識別任務通過全連接神經(jīng)網(wǎng)絡表示,如 圖3 所示。
圖3:手寫數(shù)字識別任務的全連接神經(jīng)網(wǎng)絡結構
- 輸入層:將數(shù)據(jù)輸入給神經(jīng)網(wǎng)絡。在該任務中,輸入層的尺度為28×28的像素值。
- 隱含層:增加網(wǎng)絡深度和復雜度,隱含層的節(jié)點數(shù)是可以調(diào)整的,節(jié)點數(shù)越多,神經(jīng)網(wǎng)絡表示能力越強,參數(shù)量也會增加。在該任務中,中間的兩個隱含層為10×10的結構,通常隱含層會比輸入層的尺寸小,以便對關鍵信息做抽象,激活函數(shù)使用常見的Sigmoid函數(shù)。
- 輸出層:輸出網(wǎng)絡計算結果,輸出層的節(jié)點數(shù)是固定的。如果是回歸問題,節(jié)點數(shù)量為需要回歸的數(shù)字數(shù)量。如果是分類問題,則是分類標簽的數(shù)量。在該任務中,模型的輸出是回歸一個數(shù)字,輸出層的尺寸為1。
說明:
隱含層引入非線性激活函數(shù)Sigmoid是為了增加神經(jīng)網(wǎng)絡的非線性能力。
舉例來說,如果一個神經(jīng)網(wǎng)絡采用線性變換,有四個輸入x1x_1x1?~x4x_4x4?,一個輸出yyy。假設第一層的變換是z1=x1?x2z_1=x_1-x_2z1?=x1??x2?和z2=x3+x4z_2=x_3+x_4z2?=x3?+x4?,第二層的變換是y=z1+z2y=z_1+z_2y=z1?+z2?,則將兩層的變換展開后得到y=x1?x2+x3+x4y=x_1-x_2+x_3+x_4y=x1??x2?+x3?+x4?。也就是說,無論中間累積了多少層線性變換,原始輸入和最終輸出之間依然是線性關系。
Sigmoid是早期神經(jīng)網(wǎng)絡模型中常見的非線性變換函數(shù),繪制出Sigmoid的函數(shù)曲線。
卷積神經(jīng)網(wǎng)絡
雖然使用經(jīng)典的全連接神經(jīng)網(wǎng)絡可以提升一定的準確率,但其輸入數(shù)據(jù)的形式導致丟失了圖像像素間的空間信息,這影響了網(wǎng)絡對圖像內(nèi)容的理解。對于計算機視覺問題,效果最好的模型仍然是卷積神經(jīng)網(wǎng)絡。卷積神經(jīng)網(wǎng)絡針對視覺問題的特點進行了網(wǎng)絡結構優(yōu)化,可以直接處理原始形式的圖像數(shù)據(jù),保留像素間的空間信息,因此更適合處理視覺問題。
卷積神經(jīng)網(wǎng)絡由多個卷積層和池化層組成,如 圖4 所示。卷積層負責對輸入進行掃描以生成更抽象的特征表示,池化層對這些特征表示進行過濾,保留最關鍵的特征信息。
圖4:在處理計算機視覺任務中大放異彩的卷積神經(jīng)網(wǎng)絡
說明:
本節(jié)只簡單介紹用卷積神經(jīng)網(wǎng)絡實現(xiàn)手寫數(shù)字識別任務,以及它帶來的效果提升。讀者可以將卷積神經(jīng)網(wǎng)絡先簡單的理解成是一種比經(jīng)典的全連接神經(jīng)網(wǎng)絡更強大的模型即可,更詳細的原理和實現(xiàn)在接下來的《計算機視覺-卷積神經(jīng)網(wǎng)絡基礎》中講述。
兩層卷積和池化的神經(jīng)網(wǎng)絡實現(xiàn)如下所示。
# 定義 SimpleNet 網(wǎng)絡結構
import paddle
from paddle.nn import Conv2D, MaxPool2D, Linear
import paddle.nn.functional as F
# 多層卷積神經(jīng)網(wǎng)絡實現(xiàn)
class MNIST(paddle.nn.Layer):def __init__(self):super(MNIST, self).__init__()# 定義卷積層,輸出特征通道out_channels設置為20,卷積核的大小kernel_size為5,卷積步長stride=1,padding=2self.conv1 = Conv2D(in_channels=1, out_channels=20, kernel_size=5, stride=1, padding=2)# 定義池化層,池化核的大小kernel_size為2,池化步長為2self.max_pool1 = MaxPool2D(kernel_size=2, stride=2)# 定義卷積層,輸出特征通道out_channels設置為20,卷積核的大小kernel_size為5,卷積步長stride=1,padding=2self.conv2 = Conv2D(in_channels=20, out_channels=20, kernel_size=5, stride=1, padding=2)# 定義池化層,池化核的大小kernel_size為2,池化步長為2self.max_pool2 = MaxPool2D(kernel_size=2, stride=2)# 定義一層全連接層,輸出維度是1self.fc = Linear(in_features=980, out_features=1)# 定義網(wǎng)絡前向計算過程,卷積后緊接著使用池化層,最后使用全連接層計算最終輸出# 卷積層激活函數(shù)使用Relu,全連接層不使用激活函數(shù)def forward(self, inputs):x = self.conv1(inputs)x = F.relu(x)x = self.max_pool1(x)x = self.conv2(x)x = F.relu(x)x = self.max_pool2(x)x = paddle.reshape(x, [x.shape[0], -1])x = self.fc(x)return x
使用MNIST數(shù)據(jù)集訓練定義好的卷積神經(jīng)網(wǎng)絡,如下所示。
說明:
以上數(shù)據(jù)加載函數(shù)load_data返回一個數(shù)據(jù)迭代器train_loader,該train_loader在每次迭代時的數(shù)據(jù)shape為[batch_size, 784],因此需要將該數(shù)據(jù)形式reshape為圖像數(shù)據(jù)形式[batch_size, 1, 28, 28],其中第二維代表圖像的通道數(shù)(在MNIST數(shù)據(jù)集中每張圖片的通道數(shù)為1,傳統(tǒng)RGB圖片通道數(shù)為3)。
#網(wǎng)絡結構部分之后的代碼,保持不變
def train(model):model.train()#調(diào)用加載數(shù)據(jù)的函數(shù),獲得MNIST訓練數(shù)據(jù)集train_loader = load_data('train')# 使用SGD優(yōu)化器,learning_rate設置為0.01opt = paddle.optimizer.SGD(learning_rate=0.01, parameters=model.parameters())# 訓練5輪EPOCH_NUM = 10# MNIST圖像高和寬IMG_ROWS, IMG_COLS = 28, 28loss_list = []for epoch_id in range(EPOCH_NUM):for batch_id, data in enumerate(train_loader()):#準備數(shù)據(jù)images, labels = dataimages = paddle.to_tensor(images)labels = paddle.to_tensor(labels)#前向計算的過程predicts = model(images)#計算損失,取一個批次樣本損失的平均值loss = F.square_error_cost(predicts, labels)avg_loss = paddle.mean(loss)#每訓練200批次的數(shù)據(jù),打印下當前Loss的情況if batch_id % 200 == 0:loss = avg_loss.numpy()[0]loss_list.append(loss)print("epoch: {}, batch: {}, loss is: {}".format(epoch_id, batch_id, loss))#后向傳播,更新參數(shù)的過程avg_loss.backward()# 最小化loss,更新參數(shù)opt.step()# 清除梯度opt.clear_grad()#保存模型參數(shù)paddle.save(model.state_dict(), 'mnist.pdparams')return loss_listmodel = MNIST()
loss_list = train(model)