欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

目錄

柚子快報(bào)邀請(qǐng)碼778899分享:人工智能 自然語(yǔ)言處理前饋網(wǎng)絡(luò)

柚子快報(bào)邀請(qǐng)碼778899分享:人工智能 自然語(yǔ)言處理前饋網(wǎng)絡(luò)

http://yzkb.51969.com/

內(nèi)容介紹

眾所周知,感知器是現(xiàn)存最簡(jiǎn)單的神經(jīng)網(wǎng)絡(luò)。但是感知器的一個(gè)的缺點(diǎn)就是它無法有效處理非線性可分的數(shù)據(jù)模式,這在處理復(fù)雜數(shù)據(jù)時(shí)可能導(dǎo)致其失效。例如,圖1中繪制的數(shù)據(jù)點(diǎn)。這相當(dāng)于非此即彼(XOR)的情況,在這種情況下,決策邊界不能是一條直線(線性可分)。這個(gè)例子中,感知器并不適用。

圖1 XOR數(shù)據(jù)集中的兩個(gè)類繪制為圓形和星形。我們發(fā)現(xiàn)不能用一條直線將其分開

我們將探索傳統(tǒng)上稱為前饋網(wǎng)絡(luò)的神經(jīng)網(wǎng)絡(luò)模型,以及兩種前饋神經(jīng)網(wǎng)絡(luò):多層感知器和卷積神經(jīng)網(wǎng)絡(luò)。多層感知器在結(jié)構(gòu)上擴(kuò)展了我們研究的簡(jiǎn)單感知器,將多個(gè)感知器分組在一個(gè)單層,并將多個(gè)層疊加在一起。我們稍后將首先介紹多層感知器。

我們研究的第二種前饋神經(jīng)網(wǎng)絡(luò),卷積神經(jīng)網(wǎng)絡(luò),在處理數(shù)字信號(hào)時(shí)深受窗口濾波器的啟發(fā)。通過這種窗口特性,卷積神經(jīng)網(wǎng)絡(luò)能夠在輸入中學(xué)習(xí)局部化模式,這不僅使其成為計(jì)算機(jī)視覺的主軸,而且是檢測(cè)單詞和句子等序列數(shù)據(jù)中的子結(jié)構(gòu)的理想候選。

實(shí)驗(yàn)環(huán)境

Python 3.6.7

多層感知機(jī)(The Multilayer Perceptron)

多層感知機(jī)(MLP)是一種基本的前饋神經(jīng)網(wǎng)絡(luò)模型,通過多層次的結(jié)構(gòu)實(shí)現(xiàn)對(duì)復(fù)雜模式的學(xué)習(xí)和分類任務(wù)的執(zhí)行。它擴(kuò)展了最簡(jiǎn)單形式的感知器模型,克服了感知器無法解決非線性可分問題的限制。

結(jié)構(gòu)組成

神經(jīng)元與層次結(jié)構(gòu):

神經(jīng)元(Perceptron):MLP的基本組成單元,每個(gè)神經(jīng)元接收多個(gè)輸入信號(hào),通過加權(quán)求和后應(yīng)用激活函數(shù)得出輸出。層(Layer):神經(jīng)元按層次組織,每層神經(jīng)元與前一層的所有神經(jīng)元相連,每個(gè)連接都有一個(gè)權(quán)重。 多層次的組織:

輸入層(Input Layer):接收輸入數(shù)據(jù)特征的層。隱藏層(Hidden Layer):在輸入層和輸出層之間的層,每個(gè)隱藏層都由多個(gè)神經(jīng)元組成。隱藏層的存在使得MLP能夠?qū)W習(xí)復(fù)雜的非線性關(guān)系。輸出層(Output Layer):最終產(chǎn)生MLP的輸出,通常與任務(wù)類型相關(guān)聯(lián),例如分類任務(wù)的輸出層可能是一個(gè)softmax層,回歸任務(wù)可能是一個(gè)線性層。

工作原理

前饋傳播(Feedforward Propagation):數(shù)據(jù)從輸入層經(jīng)過每一層的神經(jīng)元傳遞,通過加權(quán)求和和激活函數(shù)的計(jì)算,最終產(chǎn)生輸出。 學(xué)習(xí)與優(yōu)化:

反向傳播(Backpropagation):MLP通過反向傳播算法來學(xué)習(xí)和優(yōu)化模型參數(shù)(權(quán)重和偏置),以最小化預(yù)測(cè)輸出與實(shí)際標(biāo)簽之間的誤差。損失函數(shù)(Loss Function):用于衡量預(yù)測(cè)輸出與實(shí)際標(biāo)簽之間的差異,通常使用交叉熵(Cross-Entropy)用于分類任務(wù),均方誤差(Mean Squared Error)用于回歸任務(wù)。

優(yōu)點(diǎn)

處理非線性問題:相比于單層感知器,MLP通過多層次的非線性變換可以更好地適應(yīng)和學(xué)習(xí)復(fù)雜的數(shù)據(jù)模式和關(guān)系。 通用性:適用于多種機(jī)器學(xué)習(xí)任務(wù),如分類、回歸、聚類等,只需適當(dāng)調(diào)整輸出層和損失函數(shù)。

最簡(jiǎn)單的MLP,如圖2所示,由三個(gè)表示階段和兩個(gè)線性層組成。第一階段是輸入向量。這是給定給模型的向量。給定輸入向量,第一個(gè)線性層計(jì)算一個(gè)隱藏向量——表示的第二階段。隱藏向量之所以這樣被調(diào)用,是因?yàn)樗俏挥谳斎牒洼敵鲋g的層的輸出。

我們所說的“層的輸出”是什么意思?理解這個(gè)的一種方法是隱藏向量中的值是組成該層的不同感知器的輸出。使用這個(gè)隱藏的向量,第二個(gè)線性層計(jì)算一個(gè)輸出向量。在像Yelp評(píng)論分類這樣的二進(jìn)制任務(wù)中,輸出向量仍然可以是1。雖然在這個(gè)例子中,我們只展示了一個(gè)隱藏的向量,但是有可能有多個(gè)中間階段,每個(gè)階段產(chǎn)生自己的隱藏向量。最終的隱藏向量總是通過線性層和非線性的組合映射到輸出向量。

圖2 一種具有兩個(gè)線性層和三個(gè)表示階段(輸入向量、隱藏向量和輸出向量)的MLP的可視化表示

XOR的一個(gè)例子

根據(jù)前面對(duì)于XOR的解釋,我們?cè)谝粋€(gè)二元分類任務(wù)中訓(xùn)練感知器和MLP:星和圓。每個(gè)數(shù)據(jù)點(diǎn)是一個(gè)二維坐標(biāo)。在不深入研究實(shí)現(xiàn)細(xì)節(jié)的情況下,最終的模型預(yù)測(cè)如圖3所示。在這個(gè)圖中,錯(cuò)誤分類的數(shù)據(jù)點(diǎn)用黑色填充。在圖左中,從填充的形狀可以看出,感知器在學(xué)習(xí)一個(gè)可以將星星和圓分開的決策邊界方面有困難。然而,MLP(右邊)學(xué)習(xí)了一個(gè)更精確地對(duì)恒星和圓進(jìn)行分類的決策邊界

圖3 從感知器(左)和MLP(右)學(xué)習(xí)的XOR問題的解決方案顯示

圖3中,每個(gè)數(shù)據(jù)點(diǎn)的真正分類是該點(diǎn)的形狀:星形或圓形。在左邊的圖中,感知器學(xué)習(xí)—個(gè)不能正確地將圓與星分開的決策邊界。在右邊的圖中,MLP學(xué)會(huì)了從圓中分離星。

雖然在圖中顯示MLP有兩個(gè)決策邊界,但它實(shí)際上只是一個(gè)決策邊界,因?yàn)橹虚g表示法改變了空間,使一個(gè)超平面同時(shí)出現(xiàn)在這兩個(gè)位置上。在圖4中,我們可以看到MLP計(jì)算的中間值。這些點(diǎn)的形狀表示類(星形或圓形)。

圖4?MLP的輸入和中間表示是可視化的。從左到右:(1)網(wǎng)絡(luò)的輸入;(2)第一個(gè)線性模塊的輸出;(3)第一個(gè)非線性模塊的輸出;(4)第二個(gè)線性模塊的輸出。第一個(gè)線性模塊的輸出將圓和星分組,而第二個(gè)線性模塊的輸出將數(shù)據(jù)點(diǎn)重新組織為線性可分的。

相反,如圖5所示,感知器沒有額外的一層來處理數(shù)據(jù)的形狀,直到數(shù)據(jù)變成線性可分的。

圖5 感知器的輸入和輸出表示。因?yàn)樗鼪]有像MLP那樣的中間表示來分組和重新組織,所以它不能將圓和星分開。

在PyTorch中實(shí)現(xiàn)MLP

在本節(jié)中,我們將介紹PyTorch中的一個(gè)實(shí)現(xiàn)。如前所述,MLP除了簡(jiǎn)單的感知器之外,還有一個(gè)額外的計(jì)算層。在我們?cè)诶?-1中給出的實(shí)現(xiàn)中,我們用PyTorch的兩個(gè)線性模塊實(shí)例化了這個(gè)想法。線性對(duì)象被命名為fc1和fc2,它們遵循一個(gè)通用約定,即將線性模塊稱為“完全連接層”,簡(jiǎn)稱為“fc層”。除了這兩個(gè)線性層外,還有一個(gè)修正的線性單元(ReLU)非線性,它在被輸入到第二個(gè)線性層之前應(yīng)用于第一個(gè)線性層的輸出。由于層的順序性,必須確保層中的輸出數(shù)量等于下一層的輸入數(shù)量。使用兩個(gè)線性層之間的非線性是必要的,因?yàn)闆]有它,兩個(gè)線性層在數(shù)學(xué)上等價(jià)于一個(gè)線性層4,因此不能建模復(fù)雜的模式。MLP的實(shí)現(xiàn)只實(shí)現(xiàn)反向傳播的前向傳遞。這是因?yàn)镻yTorch根據(jù)模型的定義和向前傳遞的實(shí)現(xiàn),自動(dòng)計(jì)算出如何進(jìn)行向后傳遞和梯度更新

具體代碼如下

import torch.nn as nn

import torch.nn.functional as F

class MultilayerPerceptron(nn.Module):

def __init__(self, input_dim, hidden_dim, output_dim):

"""

初始化多層感知器(MLP)模型。

Args:

input_dim (int): 輸入向量的大小。

hidden_dim (int): 第一個(gè)全連接層的輸出大?。[藏層大?。?。

output_dim (int): 第二個(gè)全連接層的輸出大?。ㄗ罱K輸出大小)。

"""

super(MultilayerPerceptron, self).__init__()

# 定義第一個(gè)全連接層,將輸入維度映射到隱藏層維度

self.fc1 = nn.Linear(input_dim, hidden_dim)

# 定義第二個(gè)全連接層,將隱藏層維度映射到輸出維度

self.fc2 = nn.Linear(hidden_dim, output_dim)

def forward(self, x_in, apply_softmax=False):

"""

MLP的前向傳播過程。

Args:

x_in (torch.Tensor): 輸入數(shù)據(jù)張量。

x_in 的形狀應(yīng)為 (batch, input_dim)。

apply_softmax (bool): 是否應(yīng)用 softmax 激活函數(shù)的標(biāo)志。

如果與交叉熵?fù)p失函數(shù)一起使用,應(yīng)為 False。

Returns:

torch.Tensor: 輸出張量。張量形狀應(yīng)為 (batch, output_dim)。

"""

# 通過第一個(gè)全連接層并應(yīng)用 ReLU 激活函數(shù)

intermediate = F.relu(self.fc1(x_in))

# 通過第二個(gè)全連接層得到輸出

output = self.fc2(intermediate)

# 如果 apply_softmax 為真,應(yīng)用 softmax 激活函數(shù)

if apply_softmax:

output = F.softmax(output, dim=1)

return output

由于MLP實(shí)現(xiàn)的通用性,可以為任何大小的輸入建模。為了演示,我們使用大小為3的輸入維度、大小為4的輸出維度和大小為100的隱藏維度。請(qǐng)注意,在print語(yǔ)句的輸出中,每個(gè)層中的單元數(shù)很好地排列在一起,以便為維度3的輸入生成維度4的輸出。

batch_size = 2 # 一次輸入的樣本數(shù)量

input_dim = 3 # 輸入向量的維度

hidden_dim = 100 # 隱藏層的維度

output_dim = 4 # 輸出向量的維度

# 初始化多層感知器(MLP)模型

mlp = MultilayerPerceptron(input_dim, hidden_dim, output_dim)

# 打印模型結(jié)構(gòu)

print(mlp)

結(jié)果如下

MultilayerPerceptron( (fc1): Linear(in_features=3, out_features=100, bias=True) (fc2): Linear(in_features=100, out_features=4, bias=True) )

我們可以通過傳遞一些隨機(jī)輸入來快速測(cè)試模型的“連接”,如下面示例所示。因?yàn)槟P瓦€沒有經(jīng)過訓(xùn)練,所以輸出是隨機(jī)的。?

import torch

def describe(x):

"""

打印張量的類型、形狀和值。

Args:

x (torch.Tensor): 要描述的輸入張量。

"""

print("Type: {}".format(x.type())) # 打印張量的類型

print("Shape/size: {}".format(x.shape)) # 打印張量的形狀/大小

print("Values: \n{}".format(x)) # 打印張量的值

# 生成隨機(jī)輸入張量,其形狀為 (batch_size, input_dim)

x_input = torch.rand(batch_size, input_dim)

# 調(diào)用 describe 函數(shù),打印張量的信息

describe(x_input)

結(jié)果如下

Type: torch.FloatTensor Shape/size: torch.Size([2, 3]) Values: tensor([[0.6193, 0.7045, 0.7812], [0.6345, 0.4476, 0.9909]])

y_output = mlp(x_input, apply_softmax=False)

describe(y_output)

Type: torch.FloatTensor Shape/size: torch.Size([2, 4]) Values: tensor([[ 0.2356, 0.0983, -0.0111, -0.0156], [ 0.1604, 0.1586, -0.0642, 0.0010]], grad_fn=)

實(shí)際案例

案例一:基于多層感知機(jī)的姓氏分類

我們將MLP應(yīng)用于將姓氏分類到其原籍國(guó)的任務(wù)。從公開觀察到的數(shù)據(jù)推斷人口統(tǒng)計(jì)信息(如國(guó)籍)具有從產(chǎn)品推薦到確保不同人口統(tǒng)計(jì)用戶獲得公平結(jié)果的應(yīng)用。人口統(tǒng)計(jì)和其他自我識(shí)別信息統(tǒng)稱為“受保護(hù)屬性”?!霸诮:彤a(chǎn)品中使用這些屬性時(shí),必須小心?!蔽覀兪紫葘?duì)每個(gè)姓氏的字符進(jìn)行拆分,并像對(duì)待“示例:將餐館評(píng)論的情緒分類”中的單詞一樣對(duì)待它們。除了數(shù)據(jù)上的差異,字符層模型在結(jié)構(gòu)和實(shí)現(xiàn)上與基于單詞的模型基本相似.

姓氏數(shù)據(jù)集

姓氏數(shù)據(jù)集,它收集了來自18個(gè)不同國(guó)家的10,000個(gè)姓氏,這些姓氏是作者從互聯(lián)網(wǎng)上不同的姓名來源收集的。該數(shù)據(jù)集將在本課程實(shí)驗(yàn)的幾個(gè)示例中重用,并具有一些使其有趣的屬性。第一個(gè)性質(zhì)是它是相當(dāng)不平衡的。排名前三的課程占數(shù)據(jù)的60%以上:27%是英語(yǔ),21%是俄語(yǔ),14%是阿拉伯語(yǔ)。剩下的15個(gè)民族的頻率也在下降——這也是語(yǔ)言特有的特性。第二個(gè)特點(diǎn)是,在國(guó)籍和姓氏正字法(拼寫)之間有一種有效和直觀的關(guān)系。有些拼寫變體與原籍國(guó)聯(lián)系非常緊密(比如“O ‘Neill”、“Antonopoulos”、“Nagasawa”或“Zhu”)。

class SurnameDataset(Dataset):

"""

姓氏數(shù)據(jù)集類,用于加載和處理姓氏數(shù)據(jù)。

Args:

Dataset: PyTorch Dataset 類的子類。

Attributes:

_target_df (pandas.DataFrame): 包含姓氏和對(duì)應(yīng)國(guó)籍的 DataFrame。

_vectorizer (SurnameVectorizer): 用于向量化和反向量化姓氏的向量器。

"""

def __getitem__(self, index):

"""

根據(jù)給定索引返回?cái)?shù)據(jù)集中的單個(gè)樣本。

Args:

index (int): 要檢索的樣本的索引。

Returns:

dict: 包含輸入姓氏向量和目標(biāo)國(guó)籍索引的字典。

"""

# 從目標(biāo) DataFrame 中獲取具有給定索引的行

row = self._target_df.iloc[index]

# 使用向量器將姓氏向量化

surname_vector = self._vectorizer.vectorize(row.surname)

# 使用向量器查找目標(biāo)國(guó)籍的索引

nationality_index = self._vectorizer.nationality_vocab.lookup_token(row.nationality)

# 返回包含姓氏向量和目標(biāo)國(guó)籍索引的字典

return {'x_surname': surname_vector,

'y_nationality': nationality_index}

class SurnameVectorizer(object):

"""協(xié)調(diào)詞匯表并將其應(yīng)用的向量器"""

def __init__(self, surname_vocab, nationality_vocab):

"""

初始化 SurnameVectorizer 類。

Args:

surname_vocab (Vocabulary): 姓氏詞匯表。

nationality_vocab (Vocabulary): 國(guó)籍詞匯表。

"""

self.surname_vocab = surname_vocab

self.nationality_vocab = nationality_vocab

def vectorize(self, surname):

"""向量化提供的姓氏

Args:

surname (str): 姓氏字符串

Returns:

one_hot (np.ndarray): 壓縮的 one-hot 編碼

"""

vocab = self.surname_vocab

one_hot = np.zeros(len(vocab), dtype=np.float32)

for token in surname:

one_hot[vocab.lookup_token(token)] = 1

return one_hot

@classmethod

def from_dataframe(cls, surname_df):

"""從數(shù)據(jù)集 DataFrame 實(shí)例化向量器

Args:

surname_df (pandas.DataFrame): 姓氏數(shù)據(jù)集

Returns:

SurnameVectorizer 的一個(gè)實(shí)例

"""

surname_vocab = Vocabulary(unk_token="@")

nationality_vocab = Vocabulary(add_unk=False)

for index, row in surname_df.iterrows():

for letter in row.surname:

surname_vocab.add_token(letter)

nationality_vocab.add_token(row.nationality)

return cls(surname_vocab, nationality_vocab)

姓氏分類器模型

import torch.nn as nn

import torch.nn.functional as F

class SurnameClassifier(nn.Module):

"""用于對(duì)姓氏進(jìn)行分類的兩層多層感知器(MLP)"""

def __init__(self, input_dim, hidden_dim, output_dim):

"""

初始化姓氏分類器。

Args:

input_dim (int): 輸入向量的大小。

hidden_dim (int): 第一個(gè)全連接層的輸出大?。[藏層大小)。

output_dim (int): 第二個(gè)全連接層的輸出大小(最終輸出大?。?。

"""

super(SurnameClassifier, self).__init__()

# 定義第一個(gè)全連接層,將輸入維度映射到隱藏層維度

self.fc1 = nn.Linear(input_dim, hidden_dim)

# 定義第二個(gè)全連接層,將隱藏層維度映射到輸出維度

self.fc2 = nn.Linear(hidden_dim, output_dim)

def forward(self, x_in, apply_softmax=False):

"""

分類器的前向傳播過程。

Args:

x_in (torch.Tensor): 輸入數(shù)據(jù)張量。

x_in 的形狀應(yīng)為 (batch, input_dim)。

apply_softmax (bool): 是否應(yīng)用 softmax 激活函數(shù)的標(biāo)志。

如果與交叉熵?fù)p失函數(shù)一起使用,應(yīng)為 False。

Returns:

torch.Tensor: 輸出張量。張量形狀應(yīng)為 (batch, output_dim)。

"""

# 通過第一個(gè)全連接層并應(yīng)用 ReLU 激活函數(shù)

intermediate_vector = F.relu(self.fc1(x_in))

# 通過第二個(gè)全連接層得到預(yù)測(cè)向量

prediction_vector = self.fc2(intermediate_vector)

# 如果 apply_softmax 為真,應(yīng)用 softmax 激活函數(shù)

if apply_softmax:

prediction_vector = F.softmax(prediction_vector, dim=1)

return prediction_vector

常規(guī)訓(xùn)練

args = Namespace(

# Data and path information

surname_csv="data/surnames/surnames_with_splits.csv", # 姓氏數(shù)據(jù)的 CSV 文件路徑

vectorizer_file="vectorizer.json", # 向量化器的保存路徑

model_state_file="model.pth", # 模型狀態(tài)的保存路徑

save_dir="model_storage/ch4/surname_mlp", # 模型存儲(chǔ)目錄的路徑

# Model hyper parameters

hidden_dim=300, # 隱藏層的維度

# Training hyper parameters

seed=1337, # 隨機(jī)種子,用于生成隨機(jī)數(shù)

num_epochs=100, # 訓(xùn)練的最大輪數(shù)

early_stopping_criteria=5, # 提前停止訓(xùn)練的標(biāo)準(zhǔn),即驗(yàn)證集上損失連續(xù)不下降的輪數(shù)

learning_rate=0.001, # 學(xué)習(xí)率,控制模型參數(shù)更新的步長(zhǎng)

batch_size=64, # 批量訓(xùn)練時(shí)每個(gè)批次的樣本數(shù)量

)

訓(xùn)練中最顯著的差異與模型中輸出的種類和使用的損失函數(shù)有關(guān)。在這個(gè)例子中,輸出是一個(gè)多類預(yù)測(cè)向量,可以轉(zhuǎn)換為概率。正如在模型描述中所描述的,這種輸出的損失類型僅限于CrossEntropyLoss和NLLLoss。由于它的簡(jiǎn)化,我們使用了CrossEntropyLoss。

在下面例子中,我們展示了數(shù)據(jù)集、模型、損失函數(shù)和優(yōu)化器的實(shí)例化。

dataset = SurnameDataset.load_dataset_and_make_vectorizer(args.surname_csv) # 加載數(shù)據(jù)集并創(chuàng)建向量化器

vectorizer = dataset.get_vectorizer() # 獲取數(shù)據(jù)集的向量化器

# 初始化分類器模型

classifier = SurnameClassifier(input_dim=len(vectorizer.surname_vocab),

hidden_dim=args.hidden_dim,

output_dim=len(vectorizer.nationality_vocab))

classifier = classifier.to(args.device) # 將分類器模型移到指定設(shè)備上

# 定義損失函數(shù)為交叉熵?fù)p失,并考慮樣本類別不均衡情況

loss_func = nn.CrossEntropyLoss(dataset.class_weights)

# 定義優(yōu)化器為 Adam,并傳入分類器模型的參數(shù)和學(xué)習(xí)率

optimizer = optim.Adam(classifier.parameters(), lr=args.learning_rate)

本例的訓(xùn)練循環(huán)除了變量名以外幾乎是相同的。具體來說,顯示了使用不同的key從batch_dict中獲取數(shù)據(jù)。除了外觀上的差異,訓(xùn)練循環(huán)的功能保持不變。利用訓(xùn)練數(shù)據(jù),計(jì)算模型輸出、損失和梯度。然后,使用梯度來更新模型。

# Step 1: 清零梯度

optimizer.zero_grad()

# Step 2: 計(jì)算輸出

y_pred = classifier(batch_dict['x_surname'])

# Step 3: 計(jì)算損失

loss = loss_func(y_pred, batch_dict['y_nationality']) # 計(jì)算預(yù)測(cè)值與目標(biāo)值之間的損失

loss_batch = loss.to("cpu").item() # 將損失轉(zhuǎn)移到 CPU 上并提取出數(shù)值

running_loss += (loss_batch - running_loss) / (batch_index + 1) # 更新運(yùn)行損失,用于打印訓(xùn)練進(jìn)度

# Step 4: 使用損失計(jì)算梯度

loss.backward()

# Step 5: 使用優(yōu)化器執(zhí)行梯度更新步驟

optimizer.step()

顯示了分類新姓氏的代碼。給定一個(gè)姓氏作為字符串,該函數(shù)將首先應(yīng)用向量化過程,然后獲得模型預(yù)測(cè)。注意,我們包含了apply_softmax標(biāo)志,所以結(jié)果包含概率。模型預(yù)測(cè),在多項(xiàng)式的情況下,是類概率的列表。我們使用PyTorch張量最大函數(shù)來得到由最高預(yù)測(cè)概率表示的最優(yōu)類。

def predict_nationality(name, classifier, vectorizer):

"""

預(yù)測(cè)給定姓名的國(guó)籍和其概率。

Args:

name (str): 要預(yù)測(cè)的姓名。

classifier (nn.Module): 訓(xùn)練過的分類器模型。

vectorizer (SurnameVectorizer): 用于向量化姓名的向量器。

Returns:

dict: 包含預(yù)測(cè)的國(guó)籍和其概率值的字典。

"""

# 向量化姓名

vectorized_name = vectorizer.vectorize(name)

vectorized_name = torch.tensor(vectorized_name).view(1, -1) # 轉(zhuǎn)換為張量并添加批次維度

# 使用分類器進(jìn)行預(yù)測(cè)

result = classifier(vectorized_name, apply_softmax=True)

# 獲取預(yù)測(cè)概率最高的國(guó)籍

probability_values, indices = result.max(dim=1)

index = indices.item()

predicted_nationality = vectorizer.nationality_vocab.lookup_index(index)

# 獲取預(yù)測(cè)概率值

probability_value = probability_values.item()

# 返回預(yù)測(cè)結(jié)果和概率值

return {'nationality': predicted_nationality,

'probability': probability_value}

不僅要看最好的預(yù)測(cè),還要看更多的預(yù)測(cè)。例如,NLP中的標(biāo)準(zhǔn)實(shí)踐是采用k-best預(yù)測(cè)并使用另一個(gè)模型對(duì)它們重新排序。PyTorch提供了一個(gè)torch.topk函數(shù),它提供了一種方便的方法來獲得這些預(yù)測(cè)

def predict_topk_nationality(name, classifier, vectorizer, k=5):

"""

預(yù)測(cè)給定姓名的前 k 個(gè)國(guó)籍及其概率。

Args:

name (str): 要預(yù)測(cè)的姓名。

classifier (nn.Module): 訓(xùn)練過的分類器模型。

vectorizer (SurnameVectorizer): 用于向量化姓名的向量器。

k (int): 返回前 k 個(gè)國(guó)籍的數(shù)量,默認(rèn)為 5。

Returns:

list: 包含前 k 個(gè)國(guó)籍及其概率值的字典列表。

"""

# 向量化姓名

vectorized_name = vectorizer.vectorize(name)

vectorized_name = torch.tensor(vectorized_name).view(1, -1) # 轉(zhuǎn)換為張量并添加批次維度

# 使用分類器進(jìn)行預(yù)測(cè)

prediction_vector = classifier(vectorized_name, apply_softmax=True)

# 獲取前 k 個(gè)概率值和對(duì)應(yīng)的索引

probability_values, indices = torch.topk(prediction_vector, k=k)

# 將張量轉(zhuǎn)換為 numpy 數(shù)組,并提取值

probability_values = probability_values.detach().numpy()[0]

indices = indices.detach().numpy()[0]

# 構(gòu)建結(jié)果列表

results = []

for prob_value, index in zip(probability_values, indices):

nationality = vectorizer.nationality_vocab.lookup_index(index)

results.append({'nationality': nationality,

'probability': prob_value})

return results

簡(jiǎn)單地說,在訓(xùn)練過程中,dropout有一定概率使屬于兩個(gè)相鄰層的單元之間的連接減弱。這有什么用呢?我們從斯蒂芬?梅里蒂(Stephen Merity)的一段直觀(且幽默)的解釋開始:“Dropout,簡(jiǎn)單地說,是指如果你能在喝醉的時(shí)候反復(fù)學(xué)習(xí)如何做一件事,那么你應(yīng)該能夠在清醒的時(shí)候做得更好。這一見解產(chǎn)生了許多最先進(jìn)的結(jié)果和一個(gè)新興的領(lǐng)域?!?/p>

神經(jīng)網(wǎng)絡(luò)——尤其是具有大量分層的深層網(wǎng)絡(luò)——可以在單元之間創(chuàng)建有趣的相互適應(yīng)?!癈oadaptation”是神經(jīng)科學(xué)中的一個(gè)術(shù)語(yǔ),但在這里它只是指一種情況,即兩個(gè)單元之間的聯(lián)系變得過于緊密,而犧牲了其他單元之間的聯(lián)系。這通常會(huì)導(dǎo)致模型與數(shù)據(jù)過擬合。通過概率地丟棄單元之間的連接,我們可以確保沒有一個(gè)單元總是依賴于另一個(gè)單元,從而產(chǎn)生健壯的模型。dropout不會(huì)向模型中添加額外的參數(shù),但是需要一個(gè)超參數(shù)——“drop probability”。drop probability,它是單位之間的連接drop的概率。通常將下降概率設(shè)置為0.5。

import torch.nn as nn

import torch.nn.functional as F

class MultilayerPerceptron(nn.Module):

def __init__(self, input_dim, hidden_dim, output_dim):

"""

初始化多層感知器(MLP)模型。

Args:

input_dim (int): 輸入向量的大小。

hidden_dim (int): 第一個(gè)全連接層的輸出大?。[藏層大?。?。

output_dim (int): 第二個(gè)全連接層的輸出大?。ㄗ罱K輸出大?。?。

"""

super(MultilayerPerceptron, self).__init__()

self.fc1 = nn.Linear(input_dim, hidden_dim) # 第一個(gè)全連接層

self.fc2 = nn.Linear(hidden_dim, output_dim) # 第二個(gè)全連接層

def forward(self, x_in, apply_softmax=False):

"""

MLP的前向傳播過程。

Args:

x_in (torch.Tensor): 輸入數(shù)據(jù)張量。

x_in 的形狀應(yīng)為 (batch, input_dim)。

apply_softmax (bool): 是否應(yīng)用 softmax 激活函數(shù)的標(biāo)志。

如果與交叉熵?fù)p失函數(shù)一起使用,應(yīng)為 False。

Returns:

torch.Tensor: 輸出張量。張量形狀應(yīng)為 (batch, output_dim)。

"""

# 使用 ReLU 激活函數(shù)對(duì)第一個(gè)全連接層的輸出進(jìn)行非線性變換

intermediate = F.relu(self.fc1(x_in))

# 使用 dropout 對(duì)中間層進(jìn)行正則化

output = self.fc2(F.dropout(intermediate, p=0.5))

# 如果 apply_softmax 為真,應(yīng)用 softmax 激活函數(shù)

if apply_softmax:

output = F.softmax(output, dim=1)

return output

CNN超參數(shù)

為了理解不同的設(shè)計(jì)決策對(duì)CNN意味著什么,我們?cè)趫D6中展示了一個(gè)示例。在本例中,單個(gè)“核”應(yīng)用于輸入矩陣。卷積運(yùn)算(線性算子)的精確數(shù)學(xué)表達(dá)式對(duì)于理解這一節(jié)并不重要,但是從這個(gè)圖中可以直觀地看出,核是一個(gè)小的方陣,它被系統(tǒng)地應(yīng)用于輸入矩陣的不同位置。

卷積運(yùn)算的維數(shù)

首先要理解的概念是卷積運(yùn)算的維數(shù)。在圖4-6和本節(jié)的其他圖中,我們使用二維卷積進(jìn)行說明,但是根據(jù)數(shù)據(jù)的性質(zhì),還有更適合的其他維度的卷積。在PyTorch中,卷積可以是一維、二維或三維的,分別由Conv1d、Conv2d和Conv3d模塊實(shí)現(xiàn)。一維卷積對(duì)于每個(gè)時(shí)間步都有一個(gè)特征向量的時(shí)間序列非常有用。在這種情況下,我們可以在序列維度上學(xué)習(xí)模式。NLP中的卷積運(yùn)算大多是一維的卷積。另一方面,二維卷積試圖捕捉數(shù)據(jù)中沿兩個(gè)方向的時(shí)空模式;例如,在圖像中沿高度和寬度維度——為什么二維卷積在圖像處理中很流行。類似地,在三維卷積中,模式是沿著數(shù)據(jù)中的三維捕獲的。例如,在視頻數(shù)據(jù)中,信息是三維的,二維表示圖像的幀,時(shí)間維表示幀的序列。就本課程而言,我們主要使用Conv1d。

通道

非正式地,通道(channel)是指沿輸入中的每個(gè)點(diǎn)的特征維度。例如,在圖像中,對(duì)應(yīng)于RGB組件的圖像中的每個(gè)像素有三個(gè)通道。在使用卷積時(shí),文本數(shù)據(jù)也可以采用類似的概念。從概念上講,如果文本文檔中的“像素”是單詞,那么通道的數(shù)量就是詞匯表的大小。如果我們更細(xì)粒度地考慮字符的卷積,通道的數(shù)量就是字符集的大小(在本例中剛好是詞匯表)。在PyTorch卷積實(shí)現(xiàn)中,輸入通道的數(shù)量是in_channels參數(shù)。卷積操作可以在輸出(out_channels)中產(chǎn)生多個(gè)通道。您可以將其視為卷積運(yùn)算符將輸入特征維“映射”到輸出特征維。圖7和圖8說明了這個(gè)概念。

在PyTorch中實(shí)現(xiàn)CNNs

我們將通過端到端示例來利用上一節(jié)中介紹的概念。一般來說,神經(jīng)網(wǎng)絡(luò)設(shè)計(jì)的目標(biāo)是找到一個(gè)能夠完成任務(wù)的超參數(shù)組態(tài)。我們?cè)俅慰紤]在“示例:帶有多層感知器的姓氏分類”中引入的現(xiàn)在很熟悉的姓氏分類任務(wù),但是我們將使用CNNs而不是MLP。我們?nèi)匀恍枰獞?yīng)用最后一個(gè)線性層,它將學(xué)會(huì)從一系列卷積層創(chuàng)建的特征向量創(chuàng)建預(yù)測(cè)向量。這意味著目標(biāo)是確定卷積層的配置,從而得到所需的特征向量。所有CNN應(yīng)用程序都是這樣的:首先有一組卷積層,它們提取一個(gè)feature map,然后將其作為上游處理的輸入。在分類中,上游處理幾乎總是應(yīng)用線性(或fc)層。

batch_size = 2 # 輸入數(shù)據(jù)的批量大小

one_hot_size = 10 # 每個(gè)時(shí)間步的 one-hot 編碼向量的大小

sequence_width = 7 # 輸入序列的長(zhǎng)度

data = torch.randn(batch_size, one_hot_size, sequence_width) # 生成隨機(jī)輸入數(shù)據(jù)

# 定義一維卷積層

conv1 = Conv1d(in_channels=one_hot_size, out_channels=16, kernel_size=3)

# 進(jìn)行一維卷積操作

intermediate1 = conv1(data)

# 打印輸入數(shù)據(jù)和卷積后的數(shù)據(jù)的大小

print(data.size()) # 輸出輸入數(shù)據(jù)的形狀

print(intermediate1.size()) # 輸出卷積后數(shù)據(jù)的形狀

進(jìn)一步減小輸出張量的主要方法有三種。第一種方法是創(chuàng)建額外的卷積并按順序應(yīng)用它們。最終,對(duì)應(yīng)的sequence_width (dim=2)維度的大小將為1。我們?cè)诶种姓故玖藨?yīng)用兩個(gè)額外卷積的結(jié)果。一般來說,對(duì)輸出張量的約簡(jiǎn)應(yīng)用卷積的過程是迭代的,需要一些猜測(cè)工作。我們的示例是這樣構(gòu)造的:經(jīng)過三次卷積之后,最終的輸出在最終維度上的大小為1。

在本例中,盡管詞匯表和DataLoader的實(shí)現(xiàn)方式與“示例:帶有多層感知器的姓氏分類”中的示例相同,但Vectorizer的vectorize()方法已經(jīng)更改,以適應(yīng)CNN模型的需要。具體來說,正如我們?cè)谑纠?-18中的代碼中所示,該函數(shù)將字符串中的每個(gè)字符映射到一個(gè)整數(shù),然后使用該整數(shù)構(gòu)造一個(gè)由onehot向量組成的矩陣。重要的是,矩陣中的每一列都是不同的onehot向量。主要原因是,我們將使用的Conv1d層要求數(shù)據(jù)張量在第0維上具有批處理,在第1維上具有通道,在第2維上具有特性。

除了更改為使用onehot矩陣之外,我們還修改了矢量化器,以便計(jì)算姓氏的最大長(zhǎng)度并將其保存為max_surname_length

class SurnameVectorizer(object):

"""協(xié)調(diào)詞匯表并將其應(yīng)用的向量器"""

def vectorize(self, surname):

"""

將姓氏向量化為矩陣表示。

Args:

surname (str): 姓氏字符串。

Returns:

one_hot_matrix (np.ndarray): 一個(gè)包含獨(dú)熱向量的矩陣。

"""

# 初始化獨(dú)熱向量矩陣的大小

one_hot_matrix_size = (len(self.character_vocab), self.max_surname_length)

one_hot_matrix = np.zeros(one_hot_matrix_size, dtype=np.float32)

# 對(duì)每個(gè)字符在矩陣中的位置進(jìn)行編碼

for position_index, character in enumerate(surname):

character_index = self.character_vocab.lookup_token(character)

one_hot_matrix[character_index][position_index] = 1

return one_hot_matrix

@classmethod

def from_dataframe(cls, surname_df):

"""

從數(shù)據(jù)集 DataFrame 實(shí)例化向量器。

Args:

surname_df (pandas.DataFrame): 姓氏數(shù)據(jù)集。

Returns:

an instance of the SurnameVectorizer: SurnameVectorizer 的一個(gè)實(shí)例。

"""

# 初始化字符詞匯表、國(guó)籍詞匯表和最大姓氏長(zhǎng)度

character_vocab = Vocabulary(unk_token="@")

nationality_vocab = Vocabulary(add_unk=False)

max_surname_length = 0

# 遍歷數(shù)據(jù)集中的每一行

for index, row in surname_df.iterrows():

# 更新最大姓氏長(zhǎng)度

max_surname_length = max(max_surname_length, len(row.surname))

# 向字符詞匯表和國(guó)籍詞匯表添加字符和國(guó)籍

for letter in row.surname:

character_vocab.add_token(letter)

nationality_vocab.add_token(row.nationality)

# 返回實(shí)例化的向量器

return cls(character_vocab, nationality_vocab, max_surname_length)

我們?cè)诒纠惺褂玫哪P褪鞘褂梦覀冊(cè)凇熬矸e神經(jīng)網(wǎng)絡(luò)”中介紹的方法構(gòu)建的。實(shí)際上,我們?cè)谠摬糠种袆?chuàng)建的用于測(cè)試卷積層的“人工”數(shù)據(jù)與姓氏數(shù)據(jù)集中使用本例中的矢量化器的數(shù)據(jù)張量的大小完全匹配。正如在示例4-19中所看到的,它與我們?cè)凇熬矸e神經(jīng)網(wǎng)絡(luò)”中引入的Conv1d序列既有相似之處,也有需要解釋的新添加內(nèi)容。具體來說,該模型類似于“卷積神經(jīng)網(wǎng)絡(luò)”,它使用一系列一維卷積來增量地計(jì)算更多的特征,從而得到一個(gè)單特征向量。

然而,本例中的新內(nèi)容是使用sequence和ELU PyTorch模塊。序列模塊是封裝線性操作序列的方便包裝器。在這種情況下,我們使用它來封裝Conv1d序列的應(yīng)用程序。ELU是類似于實(shí)驗(yàn)3中介紹的ReLU的非線性函數(shù),但是它不是將值裁剪到0以下,而是對(duì)它們求冪。ELU已經(jīng)被證明是卷積層之間使用的一種很有前途的非線性(Clevert et al., 2015)。

在本例中,我們將每個(gè)卷積的通道數(shù)與num_channels超參數(shù)綁定。我們可以選擇不同數(shù)量的通道分別進(jìn)行卷積運(yùn)算。這樣做需要優(yōu)化更多的超參數(shù)。我們發(fā)現(xiàn)256足夠大,可以使模型達(dá)到合理的性能。

import torch.nn as nn

import torch.nn.functional as F

class SurnameClassifier(nn.Module):

def __init__(self, initial_num_channels, num_classes, num_channels):

"""

初始化姓氏分類器模型。

Args:

initial_num_channels (int): 輸入特征向量的大小。

num_classes (int): 輸出預(yù)測(cè)向量的大小(類別數(shù))。

num_channels (int): 網(wǎng)絡(luò)中使用的常量通道大小。

"""

super(SurnameClassifier, self).__init__()

# 定義卷積網(wǎng)絡(luò)層

self.convnet = nn.Sequential(

nn.Conv1d(in_channels=initial_num_channels,

out_channels=num_channels, kernel_size=3), # 第一卷積層

nn.ELU(), # 第一層的激活函數(shù)

nn.Conv1d(in_channels=num_channels, out_channels=num_channels,

kernel_size=3, stride=2), # 第二卷積層

nn.ELU(), # 第二層的激活函數(shù)

nn.Conv1d(in_channels=num_channels, out_channels=num_channels,

kernel_size=3, stride=2), # 第三卷積層

nn.ELU(), # 第三層的激活函數(shù)

nn.Conv1d(in_channels=num_channels, out_channels=num_channels,

kernel_size=3), # 第四卷積層

nn.ELU() # 第四層的激活函數(shù)

)

# 定義全連接層

self.fc = nn.Linear(num_channels, num_classes)

def forward(self, x_surname, apply_softmax=False):

"""

分類器的前向傳播過程。

Args:

x_surname (torch.Tensor): 輸入數(shù)據(jù)張量。

x_surname 的形狀應(yīng)為 (batch, initial_num_channels, max_surname_length)。

apply_softmax (bool): 是否應(yīng)用 softmax 激活函數(shù)的標(biāo)志。

如果與交叉熵?fù)p失函數(shù)一起使用,應(yīng)為 False。

Returns:

torch.Tensor: 結(jié)果張量。張量形狀應(yīng)為 (batch, num_classes)。

"""

# 使用卷積網(wǎng)絡(luò)層處理輸入數(shù)據(jù),并壓縮維度

features = self.convnet(x_surname).squeeze(dim=2)

# 使用全連接層進(jìn)行分類

prediction_vector = self.fc(features)

# 如果 apply_softmax 為真,應(yīng)用 softmax 激活函數(shù)

if apply_softmax:

prediction_vector = F.softmax(prediction_vector, dim=1)

return prediction_vector

訓(xùn)練程序包括以下似曾相識(shí)的的操作序列:實(shí)例化數(shù)據(jù)集,實(shí)例化模型,實(shí)例化損失函數(shù),實(shí)例化優(yōu)化器,遍歷數(shù)據(jù)集的訓(xùn)練分區(qū)和更新模型參數(shù),遍歷數(shù)據(jù)集的驗(yàn)證分區(qū)和測(cè)量性能,然后重復(fù)數(shù)據(jù)集迭代一定次數(shù)。此時(shí),這是本書到目前為止的第三個(gè)訓(xùn)練例程實(shí)現(xiàn),應(yīng)該將這個(gè)操作序列內(nèi)部化。對(duì)于這個(gè)例子,我們將不再詳細(xì)描述具體的訓(xùn)練例程,因?yàn)樗c“示例:帶有多層感知器的姓氏分類”中的例程完全相同。但是,輸入?yún)?shù)是不同的,可以在中看到

args = Namespace(

# 數(shù)據(jù)和路徑信息

surname_csv="data/surnames/surnames_with_splits.csv", # 姓氏數(shù)據(jù)集的 CSV 文件路徑

vectorizer_file="vectorizer.json", # 向量器的保存文件路徑

model_state_file="model.pth", # 模型狀態(tài)的保存文件路徑

save_dir="model_storage/ch4/cnn", # 模型保存的目錄路徑

# 模型超參數(shù)

hidden_dim=100, # 隱藏層的大小

num_channels=256, # CNN 中的通道數(shù)

# 訓(xùn)練超參數(shù)

seed=1337, # 隨機(jī)種子

learning_rate=0.001, # 學(xué)習(xí)率

batch_size=128, # 批量大小

num_epochs=100, # 訓(xùn)練的總輪數(shù)

early_stopping_criteria=5, # 提前停止訓(xùn)練的標(biāo)準(zhǔn)

dropout_p=0.1, # Dropout 概率

# 運(yùn)行時(shí)參數(shù)已省略 ...

)

要理解模型的性能,需要對(duì)性能進(jìn)行定量和定性的度量。下面將描述這兩個(gè)度量的基本組件。建議你擴(kuò)展它們,以探索該模型及其所學(xué)習(xí)到的內(nèi)容。

正如:帶有多層感知器的姓氏分類”中的示例與本示例之間的訓(xùn)練例程沒有變化一樣,執(zhí)行評(píng)估的代碼也沒有變化。總之,調(diào)用分類器的`eval()`方法來防止反向傳播,并迭代測(cè)試數(shù)據(jù)集。與 MLP 約 50% 的性能相比,該模型的測(cè)試集性能準(zhǔn)確率約為56%。盡管這些性能數(shù)字絕不是這些特定架構(gòu)的上限,但是通過一個(gè)相對(duì)簡(jiǎn)單的CNN模型獲得的改進(jìn)應(yīng)該足以讓您在文本數(shù)據(jù)上嘗試CNNs。

在本例中,`predict_nationality()`函數(shù)的一部分發(fā)生了更改,如示例4-21所示:我們沒有使用視圖方法重塑新創(chuàng)建的數(shù)據(jù)張量以添加批處理維度,而是使用PyTorch的`unsqueeze()`函數(shù)在批處理應(yīng)該在的位置添加大小為1的維度。相同的更改反映在`predict_topk_nationality()`函數(shù)中。

def predict_nationality(surname, classifier, vectorizer):

"""

從新的姓氏預(yù)測(cè)國(guó)籍。

Args:

surname (str): 要分類的姓氏。

classifier (SurnameClassifer): 分類器的實(shí)例。

vectorizer (SurnameVectorizer): 相應(yīng)的向量器。

Returns:

dict: 包含最可能的國(guó)籍及其概率的字典。

"""

# 將姓氏向量化

vectorized_surname = vectorizer.vectorize(surname)

vectorized_surname = torch.tensor(vectorized_surname).unsqueeze(0) # 添加批次維度

# 使用分類器進(jìn)行預(yù)測(cè)

result = classifier(vectorized_surname, apply_softmax=True)

# 獲取最大概率值及其對(duì)應(yīng)的索引

probability_values, indices = result.max(dim=1)

index = indices.item()

# 查找預(yù)測(cè)國(guó)籍對(duì)應(yīng)的標(biāo)簽

predicted_nationality = vectorizer.nationality_vocab.lookup_index(index)

probability_value = probability_values.item()

# 返回預(yù)測(cè)的國(guó)籍及其概率值

return {'nationality': predicted_nationality, 'probability': probability_value}

池化

Pooling是將高維特征映射總結(jié)為低維特征映射的操作。卷積的輸出是一個(gè)特征映射。feature map中的值總結(jié)了輸入的一些區(qū)域。由于卷積計(jì)算的重疊性,許多計(jì)算出的特征可能是冗余的。Pooling是一種將高維(可能是冗余的)特征映射總結(jié)為低維特征映射的方法。在形式上,池是一種像sum、mean或max這樣的算術(shù)運(yùn)算符,系統(tǒng)地應(yīng)用于feature map中的局部區(qū)域,得到的池操作分別稱為sum pooling、average pooling和max pooling。池還可以作為一種方法,將較大但較弱的feature map的統(tǒng)計(jì)強(qiáng)度改進(jìn)為較小但較強(qiáng)的feature map。圖4-13說明了Pooling。

批處理標(biāo)準(zhǔn)化

批處理標(biāo)準(zhǔn)化是設(shè)計(jì)網(wǎng)絡(luò)時(shí)經(jīng)常使用的一種工具。BatchNorm對(duì)CNN的輸出進(jìn)行轉(zhuǎn)換,方法是將激活量縮放為零均值和單位方差。它用于Z-transform的平均值和方差值每批更新一次,這樣任何單個(gè)批中的波動(dòng)都不會(huì)太大地移動(dòng)或影響它。BatchNorm允許模型對(duì)參數(shù)的初始化不那么敏感,并且簡(jiǎn)化了學(xué)習(xí)速率的調(diào)整(Ioffe and Szegedy, 2015)。在PyTorch中,批處理規(guī)范是在nn模塊中定義的。例4-22展示了如何用卷積和線性層實(shí)例化和使用批處理規(guī)范。

# 初始化第一個(gè)卷積層和批量歸一化層

self.conv1 = nn.Conv1d(in_channels=1, out_channels=10, kernel_size=5, stride=1)

self.conv1_bn = nn.BatchNorm1d(num_features=10)

def forward(self, x):

"""

前向傳播方法

Args:

x (torch.Tensor): 輸入數(shù)據(jù)張量,形狀為 (batch_size, input_channels, sequence_length)。

Returns:

torch.Tensor: 輸出數(shù)據(jù)張量,形狀根據(jù)模型結(jié)構(gòu)不同而不同。

"""

# 使用ReLU激活函數(shù)對(duì)第一個(gè)卷積層的輸出進(jìn)行非線性變換

x = F.relu(self.conv1(x))

# 對(duì)第一個(gè)卷積層的輸出進(jìn)行批量歸一化

x = self.conv1_bn(x)

# 這里可能還有其他層和操作

return x

Network-in-Network (NiN)連接是具有`kernel_size=1`的卷積內(nèi)核,具有一些有趣的特性。具體來說,1x1卷積就像通道之間的一個(gè)完全連通的線性層。這在從多通道feature map映射到更淺的feature map時(shí)非常有用。在圖14中,我們展示了一個(gè)應(yīng)用于輸入矩陣的NiN連接。它將兩個(gè)通道簡(jiǎn)化為一個(gè)通道。因此,NiN或1x1卷積提供了一種廉價(jià)的方法來合并參數(shù)較少的額外非線性(Lin et al., 2013)。

CNNs中最重要的趨勢(shì)之一是Residual connection,它支持真正深層的網(wǎng)絡(luò)(超過100層)。它也稱為skip connection。

然而,這個(gè)操作有一個(gè)隱含的技巧,如圖4-15所示。對(duì)于要添加到卷積輸出的輸入,它們必須具有相同的形狀。為此,標(biāo)準(zhǔn)做法是在卷積之前應(yīng)用填充。在圖5中,填充尺寸為1,卷積大小為3。

柚子快報(bào)邀請(qǐng)碼778899分享:人工智能 自然語(yǔ)言處理前饋網(wǎng)絡(luò)

http://yzkb.51969.com/

相關(guān)鏈接

評(píng)論可見,查看隱藏內(nèi)容
大家都在看:

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。

轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19081007.html

發(fā)布評(píng)論

您暫未設(shè)置收款碼

請(qǐng)?jiān)谥黝}配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問

文章目錄