prompt
使用 crnn 提取圖像特征,給出圖像好壞的二分類結果,寫清楚代碼備注,注釋清楚向量維度大小,并給出一個可運行的 demo
1、GPT-4o
以下是一個使用 CRNN(Convolutional Recurrent Neural Network)提取圖像特征并進行二分類的完整代碼示例。我們將使用 PyTorch 框架來實現。代碼中會包含詳細的注釋,解釋每一步的操作和向量維度變化。
1. 安裝依賴
首先,確保你已經安裝了 PyTorch 和 torchvision。如果沒有安裝,可以使用以下命令安裝:
pip install torch torchvision
2. 代碼實現
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, Dataset
from torchvision import transforms, datasets
import numpy as np
import matplotlib.pyplot as plt# 設置隨機種子,確保結果可復現
torch.manual_seed(42)# 定義一個簡單的自定義數據集(用于演示)
class SimpleImageDataset(Dataset):def __init__(self, num_samples=1000, img_size=(32, 32)):self.num_samples = num_samplesself.img_size = img_sizeself.data = []self.labels = []# 生成隨機圖像數據for _ in range(num_samples):# 隨機生成圖像(0-1之間的浮點數)img = np.random.rand(*img_size).astype(np.float32)# 隨機生成標簽(0 或 1)label = np.random.randint(0, 2)self.data.append(img)self.labels.append(label)def __len__(self):return self.num_samplesdef __getitem__(self, idx):# 返回圖像和標簽img = self.data[idx]label = self.labels[idx]# 將圖像轉換為 PyTorch 張量,并添加通道維度 (1, H, W)img = torch.tensor(img).unsqueeze(0) # (1, H, W)label = torch.tensor(label).long() # 標簽為整數return img, label# 定義 CRNN 模型
class CRNN(nn.Module):def __init__(self, input_channels=1, num_classes=2):super(CRNN, self).__init__()# 卷積層self.conv = nn.Sequential(nn.Conv2d(input_channels, 16, kernel_size=3, stride=1, padding=1), # (B, 16, H, W)nn.ReLU(),nn.MaxPool2d(2, 2), # (B, 16, H/2, W/2)nn.Conv2d(16, 32, kernel_size=3, stride=1, padding=1), # (B, 32, H/2, W/2)nn.ReLU(),nn.MaxPool2d(2, 2) # (B, 32, H/4, W/4))# RNN 層self.rnn_input_size = 32 * (img_size[1] // 4) # RNN 輸入大小 = 通道數 * 寬度self.rnn = nn.LSTM(self.rnn_input_size, 128, batch_first=True, bidirectional=True) # 雙向 LSTM# 全連接層self.fc = nn.Linear(128 * 2, num_classes) # 雙向 LSTM 輸出大小為 128 * 2def forward(self, x):# 輸入 x 的形狀: (B, C, H, W)batch_size = x.size(0)# 卷積層x = self.conv(x) # (B, 32, H/4, W/4)# 調整形狀以適配 RNN 輸入x = x.permute(0, 2, 3, 1) # (B, H/4, W/4, 32)x = x.view(batch_size, -1, self.rnn_input_size) # (B, H/4, 32 * W/4)# RNN 層x, _ = self.rnn(x) # (B, H/4, 128 * 2)# 取最后一個時間步的輸出x = x[:, -1, :] # (B, 128 * 2)# 全連接層x = self.fc(x) # (B, num_classes)return x# 設置超參數
img_size = (32, 32) # 圖像大小
batch_size = 16
num_epochs = 5
learning_rate = 0.001# 創建數據集和數據加載器
dataset = SimpleImageDataset(num_samples=1000, img_size=img_size)
dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)# 初始化模型、損失函數和優化器
model = CRNN(input_channels=1, num_classes=2)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)# 訓練模型
for epoch in range(num_epochs):model.train()total_loss = 0for images, labels in dataloader:# 前向傳播outputs = model(images)loss = criterion(outputs, labels)# 反向傳播和優化optimizer.zero_grad()loss.backward()optimizer.step()total_loss += loss.item()print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {total_loss/len(dataloader):.4f}")# 測試模型
model.eval()
with torch.no_grad():# 從數據集中取一個樣本進行測試test_img, test_label = dataset[0]test_img = test_img.unsqueeze(0) # 添加 batch 維度 (1, 1, H, W)output = model(test_img)predicted_label = torch.argmax(output, dim=1).item()print(f"True Label: {test_label}, Predicted Label: {predicted_label}")# 可視化測試圖像plt.imshow(test_img.squeeze(0).squeeze(0), cmap="gray")plt.title(f"Predicted: {predicted_label}, True: {test_label}")plt.show()
3. 代碼說明
-
數據集:
- 使用了一個簡單的自定義數據集
SimpleImageDataset
,生成隨機圖像和二分類標簽。 - 圖像大小為
(32, 32)
,標簽為0
或1
。
- 使用了一個簡單的自定義數據集
-
CRNN 模型:
- 卷積層提取圖像的空間特征。
- RNN 層(LSTM)處理序列特征,輸入為卷積層輸出的特征序列。
- 全連接層將 RNN 的輸出映射到二分類結果。
-
訓練:
- 使用交叉熵損失函數
CrossEntropyLoss
。 - 優化器為 Adam。
- 使用交叉熵損失函數
-
測試:
- 從數據集中取一個樣本,使用訓練好的模型進行預測,并可視化結果。
4. 運行結果
運行代碼后,你會看到訓練過程中的損失值,以及測試樣本的預測結果和真實標簽。測試圖像會以灰度圖形式顯示。
如果你有任何問題或需要進一步的幫助,請隨時告訴我! 😊
2、豆包-1.5pro
下面是一個基于PyTorch框架實現的使用CRNN(Convolutional Recurrent Neural Network)進行圖像二分類的示例代碼。這個示例假設輸入圖像為正方形且為灰度圖。對于彩色圖像,可以簡單修改卷積層以便處理3通道數據。
1. 引入必要的庫
import torch
import torch.nn as nn
import torchvision.transforms as transforms
from torchvision.datasets import ImageFolder
from torch.utils.data import DataLoader
import torch.optim as optim
from PIL import Image# 用于圖像預處理
transform = transforms.Compose([transforms.Resize((32, 32)),transforms.Grayscale(),transforms.ToTensor(),# 將圖像數據標準化到[-1, 1]transforms.Normalize((0.5,), (0.5,))
])
2. 定義CRNN模型
class CRNN(nn.Module):def __init__(self):super(CRNN, self).__init__()# 卷積層1,輸入通道數1(灰度圖),輸出通道數16,卷積核大小3x3,步長1,填充1self.conv1 = nn.Conv2d(1, 16, kernel_size=3, stride=1, padding=1)self.relu1 = nn.ReLU()# 最大池化層1,窗口大小2x2,步長2self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)# 卷積層2,輸入通道數16,輸出通道數32,卷積核大小3x3,步長1,填充1self.conv2 = nn.Conv2d(16, 32, kernel_size=3, stride=1, padding=1)self.relu2 = nn.ReLU()# 最大池化層2,窗口大小2x2,步長2self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)# 展平層,將多維張量展平為一維self.flatten = nn.Flatten()# RNN層,這里使用GRU,輸入特征維度32 * 8 * 8 ,隱藏層維度64,1層self.gru = nn.GRU(input_size=32 * 8 * 8, hidden_size=64, num_layers=1, batch_first=True)# 全連接層,將GRU輸出的64維向量映射到2維(2個類別)self.fc = nn.Linear(64, 2)def forward(self, x):x = self.pool1(self.relu1(self.conv1(x)))x = self.pool2(self.relu2(self.conv2(x)))x = self.flatten(x)x = x.unsqueeze(1)x, _ = self.gru(x)# 只取GRU最后一個時刻的輸出x = x[:, -1, :]x = self.fc(x)return x
3. 定義訓練過程
# 創建數據加載器,假設數據按類別存放在data/train目錄下
train_dataset = ImageFolder(root='data/train', transform=transform)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)# 創建模型實例
model = CRNN()# 定義損失函數和優化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)# 訓練模型
num_epochs = 10
for epoch in range(num_epochs):running_loss = 0.0correct = 0total = 0for i, data in enumerate(train_loader, 0):inputs, labels = dataoptimizer.zero_grad()outputs = model(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()running_loss += loss.item()_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()print(f'Epoch {epoch + 1}, Loss: {running_loss / len(train_loader)}, 'f'Accuracy: {correct / total * 100}%')
4. 定義預測過程
# 創建測試集數據加載器,假設數據按類別存放在data/test目錄下
test_dataset = ImageFolder(root='data/test', transform=transform)
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)# 評估模型
correct = 0
total = 0
with torch.no_grad():for data in test_loader:images, labels = dataoutputs = model(images)_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()print(f'Accuracy of the network on the test images: {correct / total * 100}%')def predict_single_image(image_path, model):img = Image.open(image_path).convert('L')img = transform(img).unsqueeze(0)with torch.no_grad():output = model(img)_, predicted = torch.max(output.data, 1)return predicted.item()
5. 運行預測
# 預測單個圖像,這里假設image.jpg是需要預測的圖像
predicted_class = predict_single_image('image.jpg', model)
print(f'Predicted class for single image: {predicted_class}')
代碼說明
- 圖像預處理:使用
transforms.Compose
將圖像調整大小為32x32,轉換為灰度圖,然后轉換為張量并進行標準化。 - CRNN模型:
- 卷積層部分:使用了兩個
Conv2d
層和對應的ReLU
激活函數以及MaxPool2d
池化層進行特征提取。Conv2d
層用于學習圖像的局部特征,池化層用于降低數據維度。 - RNN層部分:將卷積層輸出的數據展平后輸入到
GRU
層,學習序列特征(此處將圖像數據看成一個序列)。 - 全連接層:將GRU層的輸出映射到2個類別,輸出最終的分類結果。
- 卷積層部分:使用了兩個
- 訓練過程:
- 加載訓練數據集,使用
ImageFolder
和DataLoader
按批次加載數據。 - 定義損失函數(
CrossEntropyLoss
)和優化器(Adam
)。 - 在每個epoch中,前向傳播計算損失,反向傳播更新模型參數,并打印每個epoch的損失和準確率。
- 加載訓練數據集,使用
- 預測過程:
- 加載測試數據集,對測試集進行評估并打印準確率。
predict_single_image
函數用于對單個圖像進行預測,返回預測的類別。
請確保安裝了torch
、torchvision
和Pillow
庫,可以使用以下命令安裝:
pip install torch torchvision pillow
測試和訓練數據集的目錄結構應如下:
data/
├── train/
│ ├── good_images/
│ │ ├── image1.jpg
│ │ ├── image2.jpg
│ │ └──...
│ └── bad_images/
│ ├── image3.jpg
│ ├── image4.jpg
│ └──...
└── test/├── good_images/│ ├── image5.jpg│ ├── image6.jpg│ └──...└── bad_images/├── image7.jpg├── image8.jpg└──...
在實際應用中,你可以根據具體的數據集和任務需求調整模型架構、超參數等。
3、Qwen-2.5
好的,下面是一個使用CRNN(卷積循環神經網絡)提取圖像特征并用于二分類任務的PyTorch示例代碼。我們將使用一個簡單的CRNN模型來實現這個任務。代碼中會包含詳細的注釋說明每一步的操作和向量維度的變化。
首先,確保你已經安裝了必要的庫:
pip install torch torchvision
以下是完整的代碼示例:
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import transforms, datasets
from torch.utils.data import DataLoader# 定義CRNN模型
class CRNN(nn.Module):def __init__(self, num_classes=2, input_size=1024, hidden_size=512, num_layers=2):super(CRNN, self).__0__init__()self.num_classes = num_classesself.hidden_size = hidden_sizeself.num_layers = num_layers# 卷積層self.conv = nn.Sequential(nn.Conv2d(3, 64, kernel_size=(3, 3), padding=(1, 1)),nn.ReLU(),nn.MaxPool2d(kernel_size=(2, 2), stride=(2, 2)), # (B, 64, H/2, W/2)nn.Conv2d(64, 128, kernel_size=(3, 3), padding=(1, 1)),nn.ReLU(),nn.MaxPool2d(kernel_size=(2, 2), stride=(2, 2)), # (B, 128, H/4, W/4)nn.Conv2d(128, 256, kernel_size=(3, 3), padding=(1, 1)),nn.ReLU(),nn.MaxPool2d(kernel_size=(2, 2), stride=(2, 2)), # (B, 256, H/8, W/8)nn.Conv2d(256, 512, kernel_size=(3, 3), padding=(1, 1)),nn.ReLU(),nn.MaxPool2d(kernel_size=(2, 2), stride=(2, 2)) # (B, 512, H/16, W/16))# 計算經過卷積層后的輸出尺寸self.fc_input_size = 512 * (32 // 16) * (32 // 16) # 假設輸入圖像大小為 (B, 3, 32, 32)# 全連接層self.fc = nn.Linear(self.fc_input_size, input_size)# 循環層self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)# 輸出層self.fc_out = nn.Linear(hidden_size, num_classes)def forward(self, x):# 卷積層conv_out = self.conv(x) # (B, 512, H/16, W/16)batch_size, channels, height, width = conv_out.size()# 展平conv_out = conv_out.view(batch_size, channels * height, width) # (B, 512*(H/16), W/16)# 全連接層conv_out = conv_out.permute(0, 2, 1) # (B, W/16, 512*(H/16))fc_out = self.fc(conv_out) # (B, W/16, input_size)# 循環層out, _ = self.lstm(fc_out) # (B, W/16, hidden_size)# 取最后一個時間步的輸出out = out[:, -1, :] # (B, hidden_size)# 輸出層out = self.fc_out(out) # (B, num_classes)return out# 數據預處理
transform = transforms.Compose([transforms.Resize((32, 32)),transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])# 加載數據集
train_dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
test_dataset = datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)# 初始化模型、損失函數和優化器
model = CRNN(num_classes=2, input_size=1024, hidden_size=512, num_layers=2)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)# 訓練模型
num_epochs = 10
for epoch in range(num_epochs):model.train()for i, (images, labels) in enumerate(train_loader):optimizer.zero_grad()outputs = model(images)loss = criterion(outputs, labels)loss.backward()optimizer.step()if (i + 1) % 100 == 0:print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{len(train_loader)}], Loss: {loss.item():.4f}')# 驗證模型model.eval()with torch.no_grad():correct = 0total = 0for images, labels in test_loader:outputs = model(images)_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()print(f'Epoch [{epoch+1}/{num_epochs}], Accuracy: {100 * correct / total:.2f}%')# 保存模型
torch.save(model.state_dict(), 'crnn_model.pth')
代碼說明
-
CRNN模型定義:
- 卷積層:使用四個卷積層,每個卷積層后跟著一個ReLU激活函數和一個最大池化層。
- 全連接層:將卷積層的輸出展平后通過一個全連接層。
- 循環層:使用LSTM層處理時間序列數據。
- 輸出層:將LSTM的輸出通過一個全連接層得到最終的分類結果。
-
數據預處理:
- 使用
transforms
對圖像進行標準化和resize操作。
- 使用
-
數據加載:
- 使用
datasets.CIFAR10
加載CIFAR-10數據集,并創建數據加載器。
- 使用
-
訓練和驗證:
- 在每個epoch中,先對模型進行訓練,然后在測試集上進行驗證,計算分類準確率。
-
保存模型:
- 訓練完成后,保存模型的參數到文件。
希望這個示例對你有幫助!如果有任何問題,歡迎隨時提問。
4、deepseek-r1:
以下是一個使用CRNN(卷積遞歸神經網絡)進行圖像分類的完整代碼示例,包括詳細的注釋和可運行的demo。代碼使用PyTorch框架實現。
1. 環境要求
- Python 3.x
- PyTorch 1.x
- torchvision
- matplotlib(可選,用于可視化)
2. 代碼實現
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms, datasets
import numpy as np
import matplotlib.pyplot as plt# 定義CRNN模型
class CRNN(nn.Module):def __init__(self, num_classes):super(CRNN, self).__init__()# CNN部分self.cnn = nn.Sequential(# 第一層卷積nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, stride=1, padding=1),# 輸出維度:(32, 224, 224)nn.ReLU(),nn.MaxPool2d(kernel_size=2, stride=2),# 輸出維度:(32, 112, 112)# 第二層卷積nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, stride=1, padding=1),# 輸出維度:(64, 112, 112)nn.ReLU(),nn.MaxPool2d(kernel_size=2, stride=2)# 輸出維度:(64, 56, 56))# RNN部分self.rnn = nn.Sequential(# LSTM層nn.LSTM(input_size=64*56, hidden_size=128, num_layers=2, batch_first=True))# 分類器self.fc = nn.Linear(128, num_classes)def forward(self, x):# CNN特征提取x = self.cnn(x) # 輸出維度:(batch_size, 64, 56, 56)# 將CNN輸出展平并調整維度以適應RNNbatch_size = x.size(0)x = x.view(batch_size, -1, 64*56) # 輸出維度:(batch_size, 56, 64*56)# RNN處理x, _ = self.rnn(x) # 輸出維度:(batch_size, 56, 128)# 取最后一個時間步的輸出x = x[:, -1, :] # 輸出維度:(batch_size, 128)# 分類x = self.fc(x) # 輸出維度:(batch_size, num_classes)return x# 定義數據預處理
transform = transforms.Compose([transforms.Resize((224, 224)),transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225])
])# 自定義數據集(假設數據分為good和bad兩類)
class ImageDataset(Dataset):def __init__(self, root_dir, transform=None):self.root_dir = root_dirself.transform = transformself.images = []self.labels = []# 加載good圖像good_dir = f"{root_dir}/good"for img_name in os.listdir(good_dir):if img_name.endswith('.jpg'):self.images.append(f"{good_dir}/{img_name}")self.labels.append(0) # good為0# 加載bad圖像bad_dir = f"{root_dir}/bad"for img_name in os.listdir(bad_dir):if img_name.endswith('.jpg'):self.images.append(f"{bad_dir}/{img_name}")self.labels.append(1) # bad為1def __len__(self):return len(self.images)def __getitem__(self, idx):img_path = self.images[idx]label = self.labels[idx]image = Image.open(img_path).convert('RGB')if self.transform:image = self.transform(image)return image, label# 數據加載
train_dataset = ImageDataset(root_dir="path_to_train_data", transform=transform)
val_dataset = ImageDataset(root_dir="path_to_val_data", transform=transform)
test_dataset = ImageDataset(root_dir="path_to_test_data", transform=transform)train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True, num_workers=4)
val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False, num_workers=4)
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False, num_workers=4)# 初始化模型
model = CRNN(num_classes=2)# 定義損失函數和優化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)# 訓練循環
num_epochs = 10for epoch in range(num_epochs):model.train()running_loss = 0.0for images, labels in train_loader:# 前向傳播outputs = model(images)loss = criterion(outputs, labels)# 反向傳播和優化optimizer.zero_grad()loss.backward()optimizer.step()running_loss += loss.item()# 打印訓練損失print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {running_loss/len(train_loader)}")# 驗證model.eval()val_loss = 0.0val_correct = 0with torch.no_grad():for images, labels in val_loader:outputs = model(images)loss = criterion(outputs, labels)val_loss += loss.item()_, predicted = torch.max(outputs.data, 1)val_correct += (predicted == labels).sum().item()val_accuracy = val_correct / len(val_dataset)print(f"Validation Loss: {val_loss/len(val_loader)}, Accuracy: {val_accuracy}")# 測試
model.eval()
test_correct = 0
with torch.no_grad():for images, labels in test_loader:outputs = model(images)_, predicted = torch.max(outputs.data, 1)test_correct += (predicted == labels).sum().item()test_accuracy = test_correct / len(test_dataset)
print(f"Test Accuracy: {test_accuracy}")# 可視化示例
def visualize_example():# 加載測試圖像test_images, test_labels = next(iter(test_loader))outputs = model(test_images)_, predicted = torch.max(outputs.data, 1)plt.figure(figsize=(16, 8))for i in range(4):plt.subplot(2, 4, i+1)img = test_images[i].numpy().transpose(1, 2, 0)img = (img * [0.229, 0.224, 0.225]) + [0.485, 0.456, 0.406]plt.imshow(img)plt.title(f"Predicted: {predicted[i].item()}, Actual: {test_labels[i].item()}")plt.axis('off')plt.show()visualize_example()
3. 代碼說明
1. 模型結構
- CNN部分:用于提取圖像特征,包含兩個卷積層和兩個最大池化層。
- RNN部分:使用LSTM處理序列特征,提取時序信息。
- 分類器:全連接層用于最終分類。
2. 數據預處理
- 圖像resize到224x224
- 轉換為Tensor
- 標準化處理
3. 數據集
- 自定義數據集類
ImageDataset
,支持自定義數據路徑。 - 數據分為
good
和bad
兩類,分別對應標簽0和1。
4. 訓練與驗證
- 使用交叉熵損失函數
CrossEntropyLoss
- 優化器選擇Adam
- 每個epoch進行訓練和驗證,打印損失和準確率。
5. 測試與可視化
- 在測試集上評估模型性能。
- 隨機選擇4張測試圖像進行可視化,顯示預測結果與真實標簽。
4. 使用說明
- 替換
path_to_train_data
、path_to_val_data
和path_to_test_data
為實際數據路徑。 - 確保數據目錄結構如下:
train_data/good/img1.jpgimg2.jpg...bad/imgA.jpgimgB.jpg... val_data/good/...bad/... test_data/good/...bad/...
- 運行代碼,訓練模型并查看結果。
5. 依賴安裝
pip install torch torchvision matplotlib
希望這段代碼對您有所幫助!如果需要進一步調整或優化,可以根據具體需求修改網絡結構、優化器參數或數據預處理步驟。