1 介紹
圖片來自:https://zh.wikipedia.org/zh-cn/%E4%BA%BA%E5%B7%A5%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C
神經網絡一直感覺挺神奇的,江湖也說可解釋性很差,無論如何還是學學吧。借這次學習哈佛的TinyML,也就順帶弄了。
這里沒有太多的去看神經網絡的細節,主要還是偏重使用層面(對于菜鳥來說,能用大神的庫就夠了。。。)。
在神經元中,有兩個核心變量w(Weight,權重)和b(Bias,偏置)還是要理解。以?y = w*x + b為例,w 控制輸入 x 對輸出 y 的影響程度,b用于調整模型的輸出基準。簡單來說,w 負責 “縮放” 輸入特征的影響,b 負責 “偏移” 輸出結果,兩者共同配合使模型能夠學習數據中的線性或非線性關系。在訓練過程中,模型通過反向傳播算法不斷更新 w 和 b,以最小化預測誤差。
在TinyML課程中,神經網絡的練習地址:Course | edX
練習代碼地址:https://colab.research.google.com/github/tinyMLx/colabs/blob/master/2-2-5-FirstNeuralNetworkRevisited.ipynb
2 代碼
代碼整理如下:
import sysimport numpy as np
import tensorflow as tf
from tensorflow import keras# This script requires TensorFlow 2 and Python 3.
if tf.__version__.split('.')[0] != '2':raise Exception((f"The script is developed and tested for tensorflow 2. "f"Current version: {tf.__version__}"))if sys.version_info.major < 3:raise Exception((f"The script is developed and tested for Python 3. "f"Current version: {sys.version_info.major}"))my_layer = keras.layers.Dense(units=1, input_shape=[1])
model = tf.keras.Sequential([my_layer])
model.compile(optimizer='sgd', loss='mean_squared_error')xs = np.array([-1.0, 0.0, 1.0, 2.0, 3.0, 4.0], dtype=float)
ys = np.array([-3.0, -1.0, 1.0, 3.0, 5.0, 7.0], dtype=float)model.fit(xs, ys, epochs=500)print(model.predict(np.array([10.0])))print(my_layer.get_weights())my_layer_1 = keras.layers.Dense(units=2, input_shape=[1])
my_layer_2 = keras.layers.Dense(units=1)
model = tf.keras.Sequential([my_layer_1, my_layer_2])
model.compile(optimizer='sgd', loss='mean_squared_error')xs = np.array([-1.0, 0.0, 1.0, 2.0, 3.0, 4.0], dtype=float)
ys = np.array([-3.0, -1.0, 1.0, 3.0, 5.0, 7.0], dtype=float)model.fit(xs, ys, epochs=500)print(model.predict(np.array([10.0])))print(my_layer_1.get_weights())
print(my_layer_2.get_weights())value_to_predict = 10.0layer1_w1 = (my_layer_1.get_weights()[0][0][0])
layer1_w2 = (my_layer_1.get_weights()[0][0][1])
layer1_b1 = (my_layer_1.get_weights()[1][0])
layer1_b2 = (my_layer_1.get_weights()[1][1])layer2_w1 = (my_layer_2.get_weights()[0][0])
layer2_w2 = (my_layer_2.get_weights()[0][1])
layer2_b = (my_layer_2.get_weights()[1][0])neuron1_output = (layer1_w1 * value_to_predict) + layer1_b1
neuron2_output = (layer1_w2 * value_to_predict) + layer1_b2neuron3_output = (layer2_w1 * neuron1_output) + (layer2_w2 * neuron2_output) + layer2_bprint(neuron3_output)
首先導入的keras的庫。
Keras 是一個高級神經網絡 API(應用程序編程接口),它用 Python 編寫,旨在讓深度學習模型的構建、訓練和部署變得更加簡單、直觀和高效。
?它的主要特點包括:
??
- 用戶友好:提供了簡潔易懂的接口,使得開發者能夠快速構建復雜的神經網絡模型,而無需過多關注底層實現細節。
- 模塊化:將神經網絡的各個組成部分(如層、激活函數、優化器等)設計為獨立的模塊,便于組合和復用。
- 可擴展性:支持自定義層、損失函數等,以滿足特定的業務需求。
- 多后端支持:最初可以在 TensorFlow、CNTK、Theano 等深度學習框架上運行,后來成為了 TensorFlow 的官方高級 API(即 tf.keras)。
Keras 廣泛應用于學術研究、工業界開發等領域,特別適合快速原型設計、教學和解決實際的深度學習問題。無論是簡單的全連接神經網絡,還是復雜的卷積神經網絡(CNN)、循環神經網絡(RNN)等,都可以通過 Keras 便捷地實現。
之后檢查TensorFlow和Python的版本。
之后使用了1層神經網絡和2層神經網絡。最后使用同樣的數據集對模型進行了驗證。
3 代碼細節
1層神經網絡
通過數據可以看出,關系是y = 2x - 1。
核心代碼是:
my_layer = keras.layers.Dense(units=1, input_shape=[1])
model = tf.keras.Sequential([my_layer])
model.compile(optimizer='sgd', loss='mean_squared_error')xs = np.array([-1.0, 0.0, 1.0, 2.0, 3.0, 4.0], dtype=float)
ys = np.array([-3.0, -1.0, 1.0, 3.0, 5.0, 7.0], dtype=float)model.fit(xs, ys, epochs=500)
訓練 500 次,優化器是隨機梯度下降(SGD),損失函數是均方誤差(MSE)。units=1表示使用了1個神經元。
上一篇說的梯度下降,就封裝在model.fit中。
之后預測輸入值10,按照關系,應該值是19。
一開始的訓練情況:
Epoch 1/500 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 482ms/step - loss: 1.8166
Epoch 2/500 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 87ms/step - loss: 1.5706
Epoch 3/500 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 136ms/step - loss: 1.3741
最后是訓練情況:
Epoch 498/500 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 64ms/step - loss: 2.4299e-05
Epoch 499/500 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 70ms/step - loss: 2.3800e-05
Epoch 500/500 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 139ms/step - loss: 2.3311e-05
此時的預測結果是[[18.985914]]
最后計算出來的參數:
[array([[1.9979583]], dtype=float32), array([-0.99367034], dtype=float32)]
感覺神經網絡計算的參數,只能無限逼近真實值,而且有一定的上限范圍。
2層神經網絡
代碼如下:
my_layer_1 = keras.layers.Dense(units=2, input_shape=[1])
my_layer_2 = keras.layers.Dense(units=1)
model = tf.keras.Sequential([my_layer_1, my_layer_2])
model.compile(optimizer='sgd', loss='mean_squared_error')xs = np.array([-1.0, 0.0, 1.0, 2.0, 3.0, 4.0], dtype=float)
ys = np.array([-3.0, -1.0, 1.0, 3.0, 5.0, 7.0], dtype=float)model.fit(xs, ys, epochs=500)
可以看到,和上面單層神經網絡基本差不多,就只是增加了一層。這里第一層是units=2,使用了兩個神經元。第二層是units=1,使用了一個神經元。
用的數據集也是一致。
開始的訓練情況:
Epoch 1/500 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 301ms/step - loss: 37.9950
Epoch 2/500 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 53ms/step - loss: 19.0502
Epoch 3/500 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 55ms/step - loss: 11.7038
最后的訓練情況:
Epoch 498/500 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 117ms/step - loss: 3.2211e-13
Epoch 499/500 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 61ms/step - loss: 3.2211e-13
Epoch 500/500 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 68ms/step - loss: 3.2211e-13
最后計算出來的參數:
1層:[array([[-0.10459945, -1.3529563 ]], dtype=float32), array([-0.07518195, 0.46336478], dtype=float32)]
2層:[array([[ 0.554448 ], [-1.5211095]], dtype=float32), array([-0.2534862], dtype=float32)]
可以看到,此時的參數和原始參數2和-1相去甚遠。
可以使用print(model.predict(np.array([10.0])))查看輸出。
預測結果是[[18.999998]]
也可以手算,過程是:
neuron1_output = (layer1_w1 * value_to_predict) + layer1_b1
neuron2_output = (layer1_w2 * value_to_predict) + layer1_b2
neuron3_output = (layer2_w1 * neuron1_output) + (layer2_w2 * neuron2_output) + layer2_b
預測結果也是[[18.999998]]
可以看出,2層神經網絡的效果比1層好出了一個數量級。上限也更高一些。。
4 課后問題
4.1 怎么判斷層數和神經元?
層數:
輸入是低維數值(比如溫度、房價預測):隱藏層很少(1~3層)就行。
輸入是高維結構化數據(比如圖像 224×224×3):通常會用很多層(10層甚至100層)。
神經元:
輸入層神經元數 = 輸入特征數(這個是固定的)。
輸出層神經元數 = 任務要求(分類數、回歸目標數)。
隱藏層神經元數:常見初始值,介于輸入層和輸出層之間。
例子:
房價預測(10個特征):
輸入層:10
隱藏層1:16
輸出層:1(回歸)
層數:2 隱藏層足夠。
手寫數字識別(28×28=784特征):
輸入層:784
隱藏層:128 → 64
輸出層:10(分類)
層數:2~3 隱藏層。
圖像分類(224×224×3):
通常直接用 CNN 多層(幾十層以上),每層的卷積核數逐漸增多。
調試技巧:
欠擬合 → 增加層數或神經元
過擬合 → 減少層數或神經元,或加正則化(Dropout、L2)
訓練慢 → 先簡化模型找方向,再加復雜度
這些就是所謂調參俠核心技能吧?
4.2 調參俠速查
調參俠速查表:
🛠 調參俠速查表
現象 / 問題 可能原因 調整方向(超參數 & 結構) 訓練集和驗證集都準確率低 / loss 高(欠擬合) 模型容量不足 / 學習率太低 / 數據特征不足 1?? 增加層數或神經元數量2?? 換更復雜模型(CNN, LSTM, Transformer)3?? 提高學習率或用自適應優化器(Adam, RMSProp)4?? 增加特征工程或用更豐富的輸入數據 訓練集準確率高,驗證集準確率低(過擬合) 模型太復雜 / 訓練時間太長 / 數據不足 1?? 減少層數或神經元2?? 增加正則化(L1/L2、Dropout)3?? 數據增強(圖像翻轉、噪聲等)4?? 提前停止(Early Stopping) loss 不下降 / 降得很慢 學習率太低 / 梯度消失 / 數據歸一化問題 1?? 提高學習率或用學習率調度器2?? 換激活函數(ReLU、LeakyReLU)3?? 數據標準化(StandardScaler / BatchNorm) loss 一開始就很大且不變 學習率太高 / 參數初始化不當 1?? 降低學習率2?? 換權重初始化方法(He、Xavier) 結果震蕩 學習率太高 / 批大小太小 1?? 降低學習率2?? 增大 batch size 訓練速度太慢 模型過大 / I/O 瓶頸 / 硬件不足 1?? 減少模型規模2?? 用 GPU/TPU3?? 數據緩存(prefetch, cache)
📏 推薦初始架構 & 神經元數量參考
輸入特征 ≤ 20:12 隱藏層,每層 1664 神經元
輸入特征 20200:24 隱藏層,每層 64~256 神經元
高維數據(圖像/音頻):用 CNN/RNN,通道數隨層數增加
輸出層:分類數(分類任務)或 1(回歸任務)
🔄 調參流程建議
小模型快速驗證可行性(先證明能學到東西)
逐步增加復雜度(層數、神經元)
觀察驗證集(避免過擬合)
優化訓練策略(學習率、正則化)
自動調參(Optuna、Ray Tune、Keras Tuner)
4.3 LLM大語言模型和神經網絡的關系
神經網絡 → 是通用技術框架。
Transformer → 是一種特定神經網絡架構,擅長處理序列。
LLM → 是基于 Transformer 的、專門用大規模文本訓練的神經網絡。
LLM(如 GPT-4、Claude、LLaMA、GLM)本質是 超大規模的 Transformer 神經網絡,層數可能幾十層甚至上百層,參數量可以到 百億 ~ 萬億級。僅此而已。。。