第4章 “腦細胞”的模擬:神經網絡與深度學習入門
1. 引言
在上一章,我們像一位偵探,學會了使用決策樹這樣的工具,從清晰的線索(花瓣、花萼的尺寸)中推理出確定的結論(鳶尾花的種類)。但如果案情變得撲朔迷離,線索不再是簡單的數字,而是一幅模糊的監控錄像截圖(圖像),或是一段充滿暗示的匿名錄音(語音),我們該如何應對?傳統的機器學習模型,就像一位依賴明確證據的偵探,面對這種高度抽象、復雜的數據時,常常會束手無策。
這時,我們需要一位更“高級”的偵探——一位能夠模仿人類大腦,從海量、雜亂的信息中,通過直覺和經驗,自動發現深層模式的專家。這位“仿生偵探”,就是我們本章的主角:人工神經網絡(Artificial Neural Network, ANN)。
你是否曾好奇,我們的大腦是如何在毫秒之間認出一位多年未見的老友的?我們并非在腦中調用一個“if-else”規則庫,而是通過億萬個神經元的協同工作,瞬間完成了模式匹配。深度學習的革命,正是源于對這種生物智能的深刻模仿。
本章學習目標:
- 追本溯源:理解人工神經網絡的設計靈感——生物神經元的工作原理。
- 解構基本單元:掌握構成神經網絡的最小單位——**感知器(Perceptron)和神經元(Neuron)**的數學模型。
- 搭建“迷你大腦”:學會如何將單個神經元組織成層次化的網絡結構(輸入層、隱藏層、輸出層)。
- 洞悉學習的奧秘:直觀地理解神經網絡是如何通過**前向傳播(Forward Propagation)進行預測,并通過反向傳播(Backpropagation)和梯度下降(Gradient Descent)**來修正錯誤的。
- 初探深度學習框架:使用當前最流行的深度學習框架之一PyTorch或TensorFlow(Keras),親手搭建并訓練你的第一個神經網絡。
本章核心問題:
- 一個“人工神經元”是如何模擬生物神經元,對信息進行“處理”和“激活”的?
- “神經網絡”這個名字中的“網絡”體現在哪里?信息是如何在其中流動的?
- 如果神經網絡做出了錯誤的預測,它是如何“聰明地”知道應該調整網絡中哪個部分的哪個參數,以及應該調整多少的?這個過程(反向傳播)可以如何通俗地理解?
在本章,我們將踏上一段激動人心的“仿生學”之旅。我們將從最基礎的“腦細胞”開始,一步步搭建起一個能夠學習和思考的“迷你大腦”。這將是理解所有現代大語言模型(如GPT)的基石,是整個課程中最具奠基意義的章節之一。系好安全帶,我們將進入深度學習的核心腹地。
2. 正文
2.1 靈感之源:會“放電”的生物神經元
要構建人工神經網絡,我們首先要看看它的“設計藍本”——我們大腦中的生物神經元。
背景與動機
我們的大腦是一個由大約860億個神經元組成的復雜網絡。每個神經元本身是一個簡單的處理單元,但它們以極其復雜的方式相互連接,形成了強大的計算能力。20世紀40年代,科學家沃倫·麥卡洛克和沃爾特·皮茨受到生物神經科學的啟發,首次提出了一個極簡的數學模型來描述神經元的工作方式,為人工神經網絡奠定了思想基礎。
直觀比喻:生物神經元的工作流程
想象一個神經元就像一個社交達人。
- 接收信息:他有許多“耳朵”(樹突, Dendrites),用來接收來自成百上千個其他朋友(其他神經元)傳來的“八卦消息”(化學信號)。
- 信息匯總:他把所有聽到的消息匯總到自己的“大腦”(細胞體, Soma)里進行加工。請注意,并非所有朋友的話他都同樣看重,來自“閨蜜”的消息權重可能就比來自“點頭之交”的要高。
- 判斷是否轉發:當他腦中匯總的信息量(電信號)超過了一個閾值(Threshold),達到一個“不吐不快”的興奮點時,他就會做出“轉發”決策。
- 發布消息:他通過自己的“大喇叭”(軸突, Axon),將這個消息(動作電位)廣播出去,傳遞給下游的其他朋友。如果沒達到興奮點,他就選擇“保持沉默”。
這個“加權匯總 -> 判斷是否激活 -> 傳遞信息”的過程,就是神經元工作的核心邏輯。
graph LRA[上游神經元A] -- 信號1 --> D{細胞體};B[上游神經元B] -- 信號2 --> D;C[上游神經元C] -- 信號3 --> D;subgraph 單個神經元direction LRD -- "匯總信號<br/>(w1*信號1 + w2*信號2 + ...)" --> E[激活判斷<br/>(是否超過閾值?)];E -- "激活(放電)" --> F[軸突];endF -- 傳遞給下游 --> G[下游神經元];
2.2 從生物到數學:人工神經元(感知器)
現在,讓我們用數學語言來翻譯一下上面那個“社交達人”的工作流程,這就誕生了最早的人工神經元模型——感知器(Perceptron)。
原理解析
一個感知器接收多個二進制輸入((x_1, x_2, …, x_n)),并產生一個單獨的二進制輸出。
-
加權匯總:每個輸入 (x_i) 都被賦予了一個權重(weight) (w_i)。這個權重就代表了那位“社交達人”對不同朋友消息的重視程度。權重可以是正數(表示這個朋友的意見很重要,是促進因素),也可以是負數(表示這個朋友的意見需要反著聽,是抑制因素)。我們將所有輸入的加權和計算出來:
[
\text{Sum} = \sum_{i} w_i x_i + b
]
這里的 (b) 是偏置(bias),你可以把它理解為這位“社交達人”自己內心的“固有偏見”或“興奮的基礎值”。即使沒有任何朋友傳來消息,如果他天生就很“嗨”(偏置值很高),也可能達到興奮點。反之,如果他天生就很“喪”(偏置值很低),就需要特別多、特別強的正面消息才能被激活。 -
激活判斷:接下來,感知器使用一個簡單的**階躍函數(Step Function)作為激活函數(Activation Function)**來判斷輸出。
[
\text{Output} =
\begin{cases}
1 & \text{if } \text{Sum} \ge 0 \
0 & \text{if } \text{Sum} < 0
\end{cases}
]
這完美地模擬了“超過閾值就激活(輸出1),否則就抑制(輸出0)”的過程。
下圖展示了一個接收3個輸入的感知器模型:
graph TDsubgraph 感知器x1[輸入 x1] -- w1 --> Sum;x2[輸入 x2] -- w2 --> Sum;x3[輸入 x3] -- w3 --> Sum;bias[偏置 b] -- 1 --> Sum;Sum["Σ (加權和)"] --> Activation["激活函數<br/>(階躍函數)"];Activation --> Output[輸出 (0或1)];end
代碼實戰:用Python實現一個邏輯“與”門感知器
邏輯“與”(AND)門是一個簡單的邏輯單元:只有當兩個輸入都為1時,輸出才為1。我們可以用一個感知器來模擬它。
import numpy as npdef AND_gate(x1, x2):"""使用感知器模型實現一個'與'門:param x1: 輸入1 (0或1):param x2: 輸入2 (0或1):return: 感知器的輸出 (0或1)"""# 輸入向量x = np.array([x1, x2])# 權重向量。w1=0.5, w2=0.5。這兩個權重意味著我們平等地看待兩個輸入。w = np.array([0.5, 0.5])# 偏置。b=-0.7。這個負偏置意味著,需要足夠強的輸入信號才能克服它,使總和大于0。b = -0.7# 計算加權和# np.sum(w*x)就是 w1*x1 + w2*x2weighted_sum = np.sum(w*x) + b# 通過階躍函數激活if weighted_sum > 0:return 1else:return 0# --- 測試我們的'與'門 ---
print(f"AND(0, 0) = {AND_gate(0, 0)}") # 預期輸出: 0
print(f"AND(1, 0) = {AND_gate(1, 0)}") # 預期輸出: 0
print(f"AND(0, 1) = {AND_gate(0, 1)}") # 預期輸出: 0
print(f"AND(1, 1) = {AND_gate(1, 1)}") # 預期輸出: 1
預期輸出:
AND(0, 0) = 0
AND(1, 0) = 0
AND(0, 1) = 0
AND(1, 1) = 1
Q&A: 你可能會問……
- Q: 這里的權重w和偏置b是我手動設置的,這算是“學習”嗎?
- A: 問得好!這不算學習,這只是“實現”。我們是基于對“與”門邏輯的理解,手動設計了這組參數。真正的機器學習,是讓機器從大量的
(輸入, 正確輸出)
數據對中,自動地、通過訓練地找到這組合適的w
和b
。
2.3 從單個細胞到神經網絡:層次化的力量
單個感知器能解決的問題非常有限(只能解決線性可分問題)。但是,當我們把成千上萬個這樣的“神經元”連接起來,形成一個層次化的“網絡”時,奇跡就發生了。
一個典型的神經網絡由以下幾個部分組成:
- 輸入層 (Input Layer):網絡的入口,負責接收最原始的數據。輸入層有幾個神經元,就代表我們的數據有幾個特征。例如,在鳶尾花分類任務中,輸入層就有4個神經元,分別對應花萼長、花萼寬、花瓣長、花瓣寬。
- 隱藏層 (Hidden Layers):位于輸入層和輸出層之間,是神經網絡進行“深度”思考的地方。這些層對外界是不可見的,它們負責從輸入數據中提取越來越抽象、越來越復雜的特征。一個神經網絡可以沒有隱藏層(那就退化成了感知器),也可以有一個或多個隱藏層。
- 輸出層 (Output Layer):網絡的出口,負責產生最終的預測結果。輸出層神經元的數量和激活函數的形式,取決于我們的任務。
- 二分類任務:通常用1個神經元,配合Sigmoid激活函數(輸出一個0到1之間的概率)。
- 多分類任務:通常用N個神經元(N為類別數),配合Softmax激活函數(輸出N個類別各自的概率)。
- 回歸任務:通常用1個神經元,且不使用激活函數(或使用線性激活函數)。
直觀比喻:圖像識別的神經網絡
想象一個識別“貓”的深度神經網絡:
- 輸入層:接收一張圖片的所有像素點。
- 第一個隱藏層(淺層):這一層的神經元,可能會在訓練后,各自學會識別一些基礎的視覺元素,比如邊緣、角點、顏色塊。它們就像一群只負責畫“橫豎撇捺”的小學生。
- 第二個隱藏層(中層):這一層的神經元接收來自第一層的信息。它會把那些“橫豎撇捺”組合起來,學會識別更復雜的形狀,比如眼睛、鼻子、耳朵、胡須。它們就像一群能把筆畫組成“偏旁部首”的中學生。
- 第三個隱藏層(深層):這一層的神經元,會把“眼睛”、“鼻子”、“耳朵”這些部件組合起來,最終學會識別出“貓臉”這個高度抽象的概念。它們就像一位能“組字成文”的大學生。
- 輸出層:接收到“貓臉”這個強烈的信號后,最終做出判斷:“這是一只貓”。
這種層次化的特征提取,正是深度學習(“深度”就體現在隱藏層的數量多)之所以如此強大的核心原因。
*注意:上圖是一個**全連接(Fully Connected)*網絡,意味著前一層中的每一個神經元都與后一層中的所有神經元相連。
2.4 學習的機制:前向傳播與反向傳播
我們已經搭建好了網絡結構,但它的參數(權重w和偏置b)最初都是隨機的,像一個什么都不懂的“新生大腦”。我們如何訓練它呢?這個過程分為兩步:前向傳播和反向傳播。
1. 前向傳播 (Forward Propagation):進行一次“猜測”
這個過程很簡單,就是讓數據“從前到后”地流過整個網絡,得出一個預測結果。
- 我們將一個樣本數據(比如一張鳶尾花的數據)喂給輸入層。
- 輸入層的輸出,被傳遞給第一個隱藏層的每一個神經元。
- 第一個隱藏層的每個神經元,各自進行加權求和與激活,然后將它們的輸出傳遞給第二個隱藏層。
- 這個過程層層遞進,直到數據流過輸出層,產生最終的預測值(比如[0.1, 0.8, 0.1],表示模型認為這朵花有80%的概率是Versicolour)。
2. 反向傳播 (Backpropagation):一次“聰明的復盤”
現在,我們拿到了模型的“猜測”結果 y_pred
,但我們還有“標準答案” y_true
(比如,這朵花其實是Virginica,對應的標簽是[0, 0, 1])。兩者之間存在一個誤差(Loss)。現在最關鍵的問題來了:我們該如何調整網絡中成千上萬個w和b,來讓這個誤差變小呢?
直觀比喻:反向傳播
想象一下,你是一個大型公司的CEO(輸出層的誤差),公司的年度利潤目標沒有達成(預測值與真實值有差距)。你非常生氣,需要問責。
- 問責第一層(輸出層 -> 隱藏層2):你首先找到你的直屬下級——各位副總裁(隱藏層2的神經元)。你不會平均地批評他們,而是看誰負責的業務線(連接權重)對最終的利潤虧損“貢獻”最大,你就批評誰最狠。這個“貢獻度”,在數學上就是偏導數(梯度)。
- 問責第二層(隱藏層2 -> 隱藏層1):各位副總裁被批評后,他們會用同樣的方式,去問責他們各自的直屬下級——各位部門總監(隱藏層1的神經元)。一個總監會不會被批評,取決于他所支持的副總裁們被CEO批評的有多狠,以及他自己對這些副總裁的“貢獻度”有多大。
- 層層傳遞:這個問責鏈會從后往前,一層一層地傳遞下去,直到最基層的員工(輸入層的連接權重)。
- 集體調整:最終,公司里的每個人都根據自己對最終錯誤的“貢獻度”,以及上級傳達下來的“批評力度”,來微調自己的工作方式(更新參數w和b)。那些對錯誤“貢獻”最大的連接,其權重會被做最大的調整。
這個“從后向前,層層追究責任,并按貢獻度進行調整”的過程,就是反向傳播的精髓。它是一種極其高效的算法,能夠計算出損失函數對網絡中每一個參數的梯度(偏導數),從而指導我們如何最有效率地去更新參數,以降低總損失。這個更新參數的具體方法,就是我們熟悉的梯度下降法。
graph TDdirection LRA[輸入] -- 前向傳播 --> B(神經網絡<br/>參數 w, b);B -- 預測值 y_pred --> C{計算損失<br/>Loss(y_pred, y_true)};C -- 誤差信號 --> D(反向傳播<br/>計算損失對每個參數的梯度 ?w, ?b);D -- 梯度信息 --> E(參數更新<br/>w = w - η*?w<br/>b = b - η*?b);E -- 更新后的參數 --> B;
注:這里的 (\eta) 是學習率(Learning Rate),它控制了我們每次參數更新的“步子”邁多大。
通過無數次的“前向傳播 -> 計算損失 -> 反向傳播 -> 更新參數”的循環,神經網絡的參數就會被訓練得越來越好,模型也就“學會”了。
2.5 神兵利器:初探深度學習框架PyTorch
理論我們已經了然于胸,但如果讓我們用NumPy從零開始手寫前向傳播、反向傳播、梯度下降……那將是一項極其繁瑣且容易出錯的工程。幸運的是,我們有專門為此設計的“神兵利器”——深度學習框架。
背景與動機
像PyTorch和TensorFlow這樣的框架,為我們處理好了所有底層的、復雜的數學運算和優化過程。它們的核心優勢在于:
- 自動求導(Autograd):我們只需要搭建好神經網絡的結構(前向傳播),框架會自動幫我們計算所有參數的梯度。這極大地解放了我們,讓我們不用手動去實現復雜的反向傳播算法。
- GPU加速:神經網絡的計算(主要是大規模的矩陣乘法)非常適合在GPU上并行處理。這些框架能讓我們用極少的代碼,就將計算任務無縫地遷移到GPU上,獲得幾十甚至上百倍的速度提升。
- 模塊化組件:框架提供了大量預先封裝好的“積木”,如網絡層(
nn.Linear
)、激活函數(nn.ReLU
)、損失函數(nn.CrossEntropyLoss
)、優化器(optim.Adam
)等,讓我們可以像搭樂高一樣,快速地構建和實驗各種復雜的模型。
直觀比喻:NumPy vs PyTorch
- 用NumPy寫神經網絡,就像你從零開始,用磚塊、水泥、鋼筋來徒手蓋一座房子。你需要精確地計算每一個力學結構,手動搬運每一塊磚。這能讓你深刻理解建筑的原理,但效率極低,且極易“塌房”。
- 用PyTorch寫神經網絡,則像是你使用高度模塊化的預制件來建造房子。墻體、窗戶、屋頂都是在工廠里按標準生產好的(
nn.Linear
,nn.ReLU
…)。你只需要像一個設計師一樣,將這些模塊按照你的藍圖(模型結構)組裝起來即可。堅固、美觀且效率極高。
我們將以PyTorch為例進行實戰,它是目前學術界和工業界最受歡迎的框架之一,以其靈活性和簡潔的“Pythonic”風格著稱。
2.6 實戰:用PyTorch搭建神經網絡解決手寫數字識別
我們將挑戰一個比鳶尾花分類更復雜一點的任務:MNIST手寫數字識別。這是一個“計算機視覺”領域的“Hello World”項目。
場景
MNIST數據集包含了大量28x28
像素的手寫數字灰度圖片(從0到9),以及它們對應的真實標簽。我們的任務是構建一個神經網絡,輸入一張這樣的圖片,讓它能準確地識別出圖片上寫的是哪個數字。
代碼實戰
# --- 1. 導入必要的PyTorch庫 ---
import torch
import torch.nn as nn # nn模塊包含了構建神經網絡所需的所有核心組件
import torch.optim as optim # optim模塊包含了各種優化算法,如SGD, Adam
from torchvision import datasets, transforms # torchvision是PyTorch處理視覺問題的庫
from torch.utils.data import DataLoader# --- 2. 準備數據 ---
# 定義一個轉換流程:將圖片轉換成PyTorch的Tensor,并進行歸一化
# 歸一化:將像素值從[0, 255]的范圍,轉換到[-1, 1]的范圍。這有助于模型更快更好地收斂。
transform = transforms.Compose([transforms.ToTensor(), # 將PIL圖像或numpy.ndarray轉換為tensor,并將像素值縮放到[0,1]transforms.Normalize((0.5,), (0.5,)) # 將[0,1]的數據歸一化到[-1,1]
])# 下載并加載訓練數據集
# root='./data'表示數據下載到當前目錄下的data文件夾
# train=True表示加載訓練集
# download=True表示如果本地沒有,就自動下載
train_set = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
# DataLoader是一個重要工具,它幫助我們將數據集打包成一個個的批次(batch),并能自動打亂數據
train_loader = DataLoader(train_set, batch_size=64, shuffle=True)# 下載并加載測試數據集
test_set = datasets.MNIST(root='./data', train=False, download=True, transform=transform)
test_loader = DataLoader(test_set, batch_size=64, shuffle=False)# --- 3. 定義神經網絡模型 ---
# 我們通過繼承nn.Module的方式來定義自己的網絡結構
class Net(nn.Module):def __init__(self):super(Net, self).__init__()# 定義網絡層。我們這里構建一個簡單的全連接網絡# nn.Linear(in_features, out_features) 定義一個線性層(全連接層)# 28*28 = 784,這是我們輸入圖片被展平后的維度# 128是第一個隱藏層的神經元數量(這個數字是經驗性的,可以調整)self.fc1 = nn.Linear(28 * 28, 128) # 第二個隱藏層self.fc2 = nn.Linear(128, 64)# 輸出層。輸出10個值,分別對應0-9這10個數字的概率self.fc3 = nn.Linear(64, 10)# 定義激活函數self.relu = nn.ReLU()# forward方法定義了數據在網絡中的“前向傳播”路徑def forward(self, x):# x的初始形狀是 [batch_size, 1, 28, 28]# x.view(-1, 28 * 28) 將其展平成 [batch_size, 784]x = x.view(-1, 28 * 28)# 數據依次流過每一層x = self.relu(self.fc1(x)) # 第一層:線性變換 -> ReLU激活x = self.relu(self.fc2(x)) # 第二層:線性變換 -> ReLU激活x = self.fc3(x) # 輸出層:只做線性變換,因為損失函數會自動處理return x# 創建模型實例
model = Net()
print("我們定義的神經網絡結構:")
print(model)# --- 4. 定義損失函數和優化器 ---
# 交叉熵損失函數,非常適合用于多分類問題
criterion = nn.CrossEntropyLoss()
# 優化器我們選擇Adam,它是一種高效的梯度下降算法的變體
# lr=0.001是學習率
optimizer = optim.Adam(model.parameters(), lr=0.001)# --- 5. 訓練模型 ---
epochs = 3 # 我們將整個數據集完整地訓練3遍for epoch in range(epochs):running_loss = 0.0# 從train_loader中批量取出數據for images, labels in train_loader:# 1. 清零梯度:這是每次迭代前必須做的一步optimizer.zero_grad()# 2. 前向傳播:將圖片輸入模型,得到預測輸出outputs = model(images)# 3. 計算損失loss = criterion(outputs, labels)# 4. 反向傳播:計算損失對所有參數的梯度loss.backward()# 5. 更新參數:優化器根據梯度來調整模型的權重optimizer.step()running_loss += loss.item()print(f"訓練周期 {epoch+1}/{epochs} 完成, 平均損失: {running_loss/len(train_loader):.4f}")print("\n模型訓練完成!")# --- 6. 評估模型 ---
correct = 0
total = 0
# 在測試時,我們不希望計算梯度,這樣可以節省計算資源
with torch.no_grad():for images, labels in test_loader:outputs = model(images)# torch.max會返回最大值和對應的索引。我們只需要索引(即預測的類別)_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()print(f"\n模型在10000張測試圖片上的準確率: {100 * correct / total:.2f} %")
預期輸出:
我們定義的神經網絡結構:
Net((fc1): Linear(in_features=784, out_features=128, bias=True)(fc2): Linear(in_features=128, out_features=64, bias=True)(fc3): Linear(in_features=64, out_features=10, bias=True)(relu): ReLU()
)
訓練周期 1/3 完成, 平均損失: 0.3708
訓練周期 2/3 完成, 平均損失: 0.1654
訓練周期 3/3 完成, 平均損失: 0.1189模型訓練完成!模型在10000張測試圖片上的準確率: 96.55 %
Q&A: 你可能會問……
- Q: 隱藏層的數量和神經元的個數(128, 64)是怎么決定的?
- A: 這是一個非常核心的問題,被稱為網絡架構設計或超參數調整。目前,這很大程度上仍然是一門“藝術”而非精確科學,依賴于經驗、實驗和一些設計原則。對于初學者,可以從一些經典的、被驗證過的簡單結構開始模仿。通常,更深(層數多)、更寬(神經元多)的網絡有更強的學習能力,但也更容易過擬合(在訓練集上表現好,但在測試集上表現差),并且需要更多的計算資源。
- Q:
nn.ReLU
是什么?為什么不用之前感知器里的階躍函數? - A:
ReLU (Rectified Linear Unit)
是目前最常用的激活函數之一,它的數學形式是f(x) = max(0, x)
。相比于階躍函數,它有一個非常重要的優點:在x>0的區域,它的導數恒為1。而階躍函數幾乎處處導數為0。在基于梯度的學習(反向傳播)中,如果激活函數的導數總是0,梯度就無法有效地回傳,網絡就“學不動”了,這個問題被稱為“梯度消失”。ReLU在很大程度上緩解了這個問題,使得訓練更深的網絡成為可能。
3. 總結與預告
在本章,我們完成了一次從生物學到計算機科學的跨越,深入探索了深度學習的基石——人工神經網絡。
本章核心要點:
- 核心思想:神經網絡通過模擬生物神經元的工作原理,將簡單的處理單元(神經元)組織成層次化的網絡,從而實現對復雜模式的層次化特征提取。
- 基本單元:人工神經元通過對輸入進行加權求和,并通過一個激活函數(如ReLU)來決定其輸出。
- 學習機制:神經網絡的學習是一個迭代的過程,通過前向傳播做出預測,計算損失,然后通過反向傳播高效地計算梯度,最后由優化器(如Adam)利用梯度來更新網絡參數。
- 深度學習框架:以PyTorch為代表的框架,通過自動求導和模塊化的設計,極大地簡化了神經網絡的搭建和訓練過程,讓我們能專注于模型架構的設計。
- 實戰成果:我們成功地使用PyTorch構建了一個簡單的全連接神經網絡,并在MNIST手寫數字識別任務上取得了超過96%的準確率,親身體驗了深度學習的威力。
我們已經掌握了構建“大腦”的基本方法。但是,我們目前構建的“全連接神經網絡”,在處理某些特定類型的數據時,還不夠高效。例如,在處理圖像時,它沒有考慮到像素之間的空間關系;在處理語言時,它沒有考慮到詞語之間的順序關系。
在下一章 《“聽”和“看”的智慧:自然語言處理與計算機視覺基礎》 中,我們將學習兩種為特定任務“量身定做”的、更強大的神經網絡結構:專門用于“看”的卷積神經網絡(CNN)和早期用于“聽”和“讀”的循環神經網絡(RNN)。這將使我們處理真實世界中非結構化數據的能力,再上一個臺階。
4. 課后練習
- 激活函數探索:查閱資料,了解除了ReLU之外,還有哪些常用的激活函數(例如:Sigmoid, Tanh, Leaky ReLU)。請簡要描述它們各自的數學形式和優缺點。
- 代碼調優:請嘗試修改本章PyTorch實戰代碼中的超參數,看看能否獲得更高的測試準確率。你可以嘗試調整:
- 學習率(
lr
):試試把它調大(如0.01
)或調小(如0.0001
),觀察訓練過程的損失變化和最終準確率。 - 網絡寬度:改變隱藏層神經元的數量(如
fc1
改為256,fc2
改為128)。 - 訓練周期數(
epochs
):增加訓練周期,看看準確率是否會繼續提升。
- 學習率(
- 思辨題:我們提到,更深、更寬的網絡有更強的學習能力,但也更容易“過擬合”。請用你自己的話解釋一下,什么是“過擬合”?并用一個生活中的例子來比喻它(例如:一個只會死記硬背、不會舉一反三的學生)。