
什么是GPT-4?完整指南
from tensorflow.keras import datasets, layers, models
# 加載MNIST數據集
(train_images, train_labels), (test_images, test_labels) = datasets.mnist.load_data()
# 對數據進行歸一化處理,將像素值縮放到0到1之間
train_images, test_images = train_images / 255.0, test_images / 255.0
# 擴展維度,使數據形狀符合卷積神經網絡輸入要求(原本是 (60000, 28, 28) 變為 (60000, 28, 28, 1))
train_images = tf.expand_dims(train_images, -1)
test_images = tf.expand_dims(test_images, -1)
# 構建卷積神經網絡模型
model = models.Sequential()
# 第一個卷積層,32個卷積核,卷積核大小3x3,激活函數用ReLU,輸入形狀為 (28, 28, 1)
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)))
model.add(layers.MaxPooling2D((2, 2)))
# 第二個卷積層
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
# 將卷積層輸出展平,以便連接全連接層
model.add(layers.Flatten())
# 全連接層,有128個神經元,激活函數用ReLU
model.add(layers.Dense(128, activation='relu'))
# 輸出層,10個神經元對應10個數字類別,激活函數用softmax
model.add(layers.Dense(10, activation='softmax'))
# 編譯模型,指定優化器、損失函數和評估指標
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# 訓練模型
model.fit(train_images, train_labels, epochs=5, batch_size=64)
# 在測試集上評估模型
test_loss, test_acc = model.evaluate(test_images, test_labels)
print(f"測試準確率: {test_acc}")
這個簡單的 CNN 包含了卷積層(用于提取圖像特征)、池化層(降采樣層,進行特征降維)以及全連接層(用于分類決策)等常見結構,通過在 MNIST 數據集上的訓練和評估來展示其基本的工作流程。如果想用于其他圖像相關任務,通常需要根據具體的圖像數據特點(比如圖像尺寸、類別數量等)來相應地修改網絡結構和訓練參數等內容。
下面來給大家講講這簡單的CNN每一層的功能:
先說這卷積層吧,你可以把它想象成是一個能從圖像里找特點的小能手。它里面有好多那種小小的 “工具”,就好比一個個小篩子一樣,這些 “小篩子” 在圖像上呀,就像掃地似的,這掃掃那掃掃,從圖像的各個地方把那些有用的特點給找出來。
比如說圖像里物體的邊邊,或者是那種紋理啥的,通過這些 “小篩子” 一弄,原來的圖像就變成了另外一種有這些特點的圖啦,而且一個卷積層里可有好多個這樣的 “小篩子” 同時干活,這樣就能從好多不同的角度把圖像的各種特點都給找出來了。
再講講池化層,這個池化層的作用就是給前面找出來的那些特點降降量,為啥要降量呢?因為前面弄出來的那些特點信息太多啦,電腦處理起來就挺費勁的,而且太多了也容易出問題呀。
那它咋降量呢?有兩種常見的辦法,一種就是找最大的,啥意思呢?就是在圖像的一小塊地方里,挑出那個數值最大的,然后就用這個最大的代表這一小塊地方,整個圖像都這么弄一遍,圖像就變小了,但是重要的特點還留著呢。還有一種辦法就是算平均,就是把那一小塊地方里的數值都加一塊兒,然后除以個數,算出個平均數來代表這小塊地方,反正不管用哪種辦法吧,最后就是讓那些特點信息變少了,電腦處理起來就輕松多啦。
最后就是全連接層,這個全連接層呢,就像是個做決定的大管家一樣。它先把前面弄好的那些特點信息都整理到一塊兒,變成一條長長的 “信息鏈”,然后呢,它里面有好多小 “工作人員”,每個 “工作人員” 都跟這 “信息鏈” 上的每個東西連著呢,它們按照自己的一套辦法算一算,最后就能告訴你這個圖像大概是屬于哪一類的啦,比如說這圖像里畫的是個啥東西呀,是貓還是狗之類的,它就能給個判斷出來。
這么一個簡單的 CNN 呢,就是靠著這幾個部分互相配合,就能完成處理圖像的事了。
這里再給出一個Pytorch的實現,這些代碼都可以直接使用:
import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
# 定義數據預處理操作,將圖像轉換為張量并歸一化
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))
])
# 加載MNIST訓練數據集
trainset = torchvision.datasets.MNIST(root='./data', train=True,
download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64,
shuffle=True, num_workers=2)
# 加載MNIST測試數據集
testset = torchvision.datasets.MNIST(root='./data', train=False,
download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=64,
shuffle=False, num_workers=2)
# 定義卷積神經網絡模型結構
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 32, 3) # 輸入通道1(灰度圖像),32個卷積核,卷積核大小3x3
self.pool = nn.MaxPool2d(2, 2) # 最大池化層,池化核2x2
self.conv2 = nn.Conv2d(32, 64, 3) # 第二層卷積,輸入通道32,64個卷積核,卷積核大小3x3
self.fc1 = nn.Linear(64 * 12 * 12, 128) # 全連接層,將卷積層輸出展平后連接
self.fc2 = nn.Linear(128, 10) # 輸出層,對應10個數字類別
def forward(self, x):
x = self.pool(torch.relu(self.conv1(x)))
x = self.pool(torch.relu(self.conv2(x)))
x = x.view(-1, 64 * 12 * 12)
x = torch.relu(self.fc1(x))
x = self.fc2(x)
return x
net = Net()
# 定義損失函數和優化器
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=0.001)
# 訓練網絡
for epoch in range(5): # 訓練輪數可以按需調整
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
inputs, labels = data
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
if i % 200 == 199:
print(f'[{epoch + 1}, {i + 1}] loss: {running_loss / 200}')
running_loss = 0.0
print('訓練完成')
# 在測試集上測試網絡
correct = 0
total = 0
with torch.no_grad():
for data in testloader:
images, labels = data
outputs = net(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f'測試集上的準確率: {100 * correct / total}%')
下面講講RNN的實現,老樣子依舊先給出一份代碼,然后我再根據這份代碼來講解RNN。
import tensorflow as tf
import numpy as np
# 1. 準備模擬數據
# 設定時間序列的長度,也就是每個樣本包含的數據點個數
time_steps = 10
# 批量大小,一次處理多少個樣本
batch_size = 32
# 輸入數據的維度,這里簡單設為1(例如單變量的時間序列,像股票價格隨時間變化這種)
input_dim = 1
# 輸出數據的維度,同樣設為1,比如預測下一個時間點的值
output_dim = 1
# 生成模擬的輸入數據,形狀為 (批量大小, 時間序列長度, 輸入維度)
x = np.linspace(0, 20 * np.pi, time_steps * batch_size).reshape(batch_size, time_steps, input_dim)
# 對應的輸出數據(這里簡單以正弦函數為例生成目標輸出,模擬預測下一個時間點的正弦值)
y = np.sin(x).reshape(batch_size, time_steps, output_dim)
# 2. 定義RNN的相關參數
# RNN單元中的隱藏單元數量,決定了模型的復雜度和對數據特征的學習能力
hidden_units = 32
# 3. 定義輸入占位符(placeholder),這是TensorFlow中用于輸入數據的一種機制
# 第一個None表示批量大小可以在運行時動態指定,后面的維度對應時間序列長度和輸入維度
X = tf.placeholder(tf.float32, [None, time_steps, input_dim])
# 同樣,為輸出數據定義占位符
Y = tf.placeholder(tf.float32, [None, time_steps, output_dim])
# 4. 定義RNN的權重和偏置(這是模型學習的參數)
# 用于將輸入轉換到隱藏狀態的權重,形狀為 (輸入維度, 隱藏單元數量)
weights_input_hidden = tf.Variable(tf.random_normal([input_dim, hidden_units]))
# 隱藏狀態到隱藏狀態的權重(因為RNN在每個時間步會用上一時刻的隱藏狀態更新當前隱藏狀態),形狀為 (隱藏單元數量, 隱藏單元數量)
weights_hidden_hidden = tf.Variable(tf.random_normal([hidden_units, hidden_units]))
# 隱藏狀態到輸出的權重,形狀為 (隱藏單元數量, 輸出維度)
weights_hidden_output = tf.Variable(tf.random_normal([hidden_units, output_dim]))
# 輸入到隱藏層的偏置,形狀為 (隱藏單元數量,)
bias_input_hidden = tf.Variable(tf.zeros([hidden_units]))
# 隱藏層到隱藏層的偏置,形狀為 (隱藏單元數量,)
bias_hidden_hidden = tf.Variable(tf.zeros([hidden_units]))
# 隱藏層到輸出的偏置,形狀為 (輸出維度,)
bias_hidden_output = tf.Variable(tf.zeros([output_dim]))
# 5. 定義RNN的計算邏輯(這里手動實現簡單的循環計算過程)
def rnn_cell(inputs, hidden_state):
"""
這是定義單個時間步的RNN單元計算邏輯的函數。
參數:
- inputs: 當前時間步的輸入數據,形狀為 (批量大小, 輸入維度)
- hidden_state: 上一個時間步的隱藏狀態,形狀為 (批量大小, 隱藏單元數量)
返回值:
- new_hidden_state: 當前時間步更新后的隱藏狀態,形狀為 (批量大小, 隱藏單元數量)
"""
# 先將輸入數據進行線性變換(乘以權重并加上偏置),為了和隱藏狀態進行相加
input_transformed = tf.matmul(tf.reshape(inputs, [-1, input_dim]), weights_input_hidden) + bias_input_hidden
# 將變換后的輸入重塑為合適的形狀,方便后續計算
input_transformed = tf.reshape(input_transformed, [-1, hidden_units])
# 用上一時刻的隱藏狀態進行線性變換
hidden_transformed = tf.matmul(hidden_state, weights_hidden_hidden) + bias_hidden_hidden
# 將變換后的輸入和隱藏狀態相加,得到新的隱藏狀態(這就是RNN的核心更新步驟)
new_hidden_state = tf.tanh(input_transformed + hidden_transformed)
return new_hidden_state
# 初始化第一個時間步的隱藏狀態為全0,形狀為 (批量大小, 隱藏單元數量)
initial_hidden_state = tf.zeros([batch_size, hidden_units])
# 循環遍歷每個時間步,逐步計算隱藏狀態
all_hidden_states = []
current_hidden_state = initial_hidden_state
for step in range(time_steps):
"""
這里通過循環來模擬RNN在每個時間步的計算過程。
"""
# 獲取當前時間步的輸入數據
current_input = X[:, step, :]
# 使用rnn_cell函數計算當前時間步的隱藏狀態更新
current_hidden_state = rnn_cell(current_input, current_hidden_state)
# 將當前時間步的隱藏狀態保存下來,方便后續使用
all_hidden_states.append(current_hidden_state)
# 將所有時間步的隱藏狀態堆疊起來,形狀變為 (時間序列長度, 批量大小, 隱藏單元數量)
all_hidden_states = tf.stack(all_hidden_states, axis=0)
# 調整隱藏狀態的順序,使其符合常規的 (批量大小, 時間序列長度, 隱藏單元數量) 格式
all_hidden_states = tf.transpose(all_hidden_states, [1, 0, 2])
# 6. 計算輸出(根據最終的隱藏狀態得到預測的輸出)
# 取最后一個時間步的隱藏狀態(這里假設我們只關心最后時刻的輸出,實際應用中可根據需求調整)
last_hidden_state = all_hidden_states[:, -1, :]
# 通過線性變換將隱藏狀態轉換為輸出數據
outputs = tf.matmul(last_hidden_state, weights_hidden_output) + bias_hidden_output
# 7. 定義損失函數(這里使用均方誤差,衡量預測值和真實值之間的差距)
loss = tf.reduce_mean(tf.square(outputs - Y))
# 8. 定義優化器(這里使用Adam優化器來更新模型的權重,讓損失函數盡量變小)
optimizer = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss)
# 9. 創建會話并進行訓練
with tf.Session() as sess:
# 初始化所有變量
sess.run(tf.global_variables_initializer())
# 進行多輪訓練
for epoch in range(100):
_, current_loss = sess.run([optimizer, loss], feed_dict={X: x, Y: y})
if epoch % 10 == 0:
print(f'Epoch {epoch}: Loss = {current_loss}')
# 訓練完成后,可以用訓練好的模型進行預測(這里簡單示例,實際應用中可按需擴展)
prediction = sess.run(outputs, feed_dict={X: x})
print("預測結果示例:", prediction[0])
這就是數據進入 RNN 的 “大門” ,就好比你要往一個機器里放東西,那輸入層就是放數據的地方。比如說我要是處理一句話,那就把這句話里的一個個字或者詞按照順序,一個一個送進去,這就是最開始數據進來的那一步。
隱藏層呢是 RNN 里很關鍵的部分。它里面有一個個小小的 “計算單元”,這些單元在每個時間步都會工作。啥是時間步呢?就是按順序處理數據的時候,每處理一個小部分就是一個時間步,像處理一句話里的每一個字的時候,處理每個字那就是一個時間步。
在每個時間步里,這個隱藏層的計算單元會拿到當前輸入的數據,然后還會參考上一個時間步自己算出來的一個 “狀態”,把這倆東西結合起來,再經過一番計算,得出一個新的 “狀態”,留著給下一個時間步接著用。就好像這個計算單元有個小 “記憶”,能記住之前算出來的東西,然后再接著往下算。
而且隱藏層里的這些計算單元會重復這樣的操作,一個時間步接著一個時間步地算下去,直到把咱送進去的一整串數據,比如一整句話,都處理完為止。
等隱藏層把所有的數據都處理完了,就輪到輸出層登場啦。輸出層就是根據隱藏層最后給出的那個 “狀態”,來得出一個結果。比如說我要是想判斷一句話是啥意思,或者預測下一個字可能是啥,那輸出層就會根據隱藏層最后的那個狀態,給出它的 “答案”,就像告訴咱們它琢磨出來這句話大概表達什么,或者覺得下一個字可能是啥樣的。
而現在模型庫都已經內置實現好了的RNN,要使用的話可以直接調用就行。
import tensorflow as tf
import numpy as np
# 生成一些模擬的時間序列數據示例(這里簡單生成正弦函數相關的數據當作示例)
time_steps = 20
batch_size = 32
input_dim = 1
output_dim = 1
# 生成輸入數據
x = np.linspace(0, 20 * np.pi, time_steps * batch_size).reshape(batch_size, time_steps, input_dim)
y = np.sin(x).reshape(batch_size, time_steps, output_dim)
# 定義RNN模型
model = tf.keras.Sequential([
tf.keras.layers.SimpleRNN(units=32, return_sequences=True, input_shape=(time_steps, input_dim)),
tf.keras.layers.Dense(units=output_dim)
])
# 編譯模型,指定優化器、損失函數等
model.compile(optimizer='adam', loss='mean_squared_error')
# 訓練模型
model.fit(x, y, epochs=10, batch_size=batch_size)
# 使用模型進行預測(這里只是簡單演示預測下一步,實際可以按需拓展)
new_x = np.linspace(20 * np.pi, 21 * np.pi, time_steps).reshape(1, time_steps, input_dim)
predicted_y = model.predict(new_x)
print(predicted_y
下面還有pytorch的調用:
import torch
import torch.nn as nn
# 超參數
input_size = 1
hidden_size = 32
num_layers = 1
output_size = 1
sequence_length = 20
# 生成模擬輸入數據(類似上面的示例,簡單用正弦函數相關模擬)
x = torch.linspace(0, 20 * torch.pi, sequence_length).unsqueeze(1).unsqueeze(0).repeat(1, 1, 1)
y = torch.sin(x).squeeze(-1)
# 定義RNN模型類
class RNN(nn.Module):
def __init__(self, input_size, hidden_size, num_layers, output_size):
super(RNN, self).__init__()
self.hidden_size = hidden_size
self.num_layers = num_layers
self.rnn = nn.RNN(input_size, hidden_size, num_layers, batch_first=True)
self.fc = nn.Linear(hidden_size, output_size)
def forward(self, x):
h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
out, _ = self.rnn(x, h0)
out = self.fc(out[:, -1, :])
return out
rnn_model = RNN(input_size, hidden_size, num_layers, output_size)
# 定義損失函數和優化器
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(rnn_model.parameters())
# 訓練模型
for epoch in range(100):
optimizer.zero_grad()
output = rnn_model(x)
loss = criterion(output, y)
loss.backward()
optimizer.step()
if epoch % 10 == 0:
print(f'Epoch {epoch}: Loss {loss.item()}')
# 進行簡單預測(示例,可按需拓展)
new_x = torch.linspace(20 * torch.pi, 21 * torch.pi, sequence_length).unsqueeze(1).unsqueeze(0)
predicted_y = rnn_model(new_x)
print(predicted_y)
本文章轉載微信公眾號@Chal1ceAI