pytorch卷积神经网络实现二分类
下面是一个简单的卷积神经网络(CNN)用于区分。
·
人工智能例子汇总:AI常见的算法和例子-CSDN博客
下面是一个简单的卷积神经网络(CNN)用于区分实心圆和方形圆的二分类任务。数据集是人工生成的图像
CNN 是专门用于处理图像等具有空间结构数据的神经网络。其核心组成部分如下:
- 输入层(Input Layer):接受原始图像数据,如 28×28×3 的彩色图片(RGB 三通道)。
- 卷积层(Convolutional Layer):提取图像特征,如边缘、纹理、形状。
- 激活函数(ReLU):引入非线性,提高模型表达能力。
- 池化层(Pooling Layer):减少计算量,提高模型对位置变化的鲁棒性。
- 全连接层(Fully Connected Layer, FC):将特征映射到最终的分类任务。
- 输出层(Output Layer):使用 Softmax(分类)或回归输出
-
数据生成
generate_circle_image(shape, size=28): 生成 28×28 的灰度图像,包含实心圆或方形圆。generate_dataset(num_samples=1000): 生成包含num_samples个样本的数据集,每个样本由 28×28 的图像和标签(0:实心圆,1:方形圆)组成。
-
模型
CNN(): 一个简单的 3 层卷积神经网络,包含 ReLU 激活和最大池化层。
-
训练
train(): 训练模型,使用二元交叉熵损失(BCEWithLogitsLoss)和 Adam 优化器。
-
测试
test(): 评估模型准确率,并可视化预测结果。
完整代码:
import torch
import torch.nn as nn
import torch.optim as optim
import torch.utils.data as Data
import matplotlib.pyplot as plt
import random
# 生成实心圆或方形圆的 28×28 图像
def generate_circle_image(shape, size=28):
"""生成 28x28 的灰度图像,包含实心圆或方形圆"""
image = torch.ones((size, size), dtype=torch.float32) # 初始化背景为 1(白色)
y, x = torch.meshgrid(torch.arange(size), torch.arange(size), indexing='ij') # 确保未来 PyTorch 版本兼容
center = (size // 2, size // 2) # 圆心坐标
radius = size // 4 # 圆的半径
if shape == 'circle':
mask = (x - center[1]) ** 2 + (y - center[0]) ** 2 <= radius ** 2 # 圆的方程
elif shape == 'square':
half_size = radius
mask = (abs(x - center[1]) <= half_size) & (abs(y - center[0]) <= half_size) # 方形范围
image[mask] = 0 # 图形部分设为 0(黑色)
return image
# 生成训练和测试数据
def generate_dataset(num_samples=1000):
"""生成数据集,包含 num_samples 个样本,每个样本是 28x28 图像和标签"""
images = []
labels = []
for _ in range(num_samples):
shape = random.choice(['circle', 'square']) # 随机选择类别
label = 0 if shape == 'circle' else 1 # 圆: 0,方形圆: 1
img = generate_circle_image(shape)
images.append(img.unsqueeze(0)) # 增加通道维度 (1, 28, 28)
labels.append(label)
images = torch.stack(images) # 转换为张量 (num_samples, 1, 28, 28)
labels = torch.tensor(labels, dtype=torch.float32) # 标签张量
return images, labels
# 卷积神经网络
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.conv1 = nn.Conv2d(1, 8, kernel_size=3, padding=1) # 1 输入通道 -> 8 输出通道
self.conv2 = nn.Conv2d(8, 16, kernel_size=3, padding=1) # 8 -> 16 输出通道
self.pool = nn.MaxPool2d(kernel_size=2, stride=2) # 2x2 最大池化层
self.fc1 = nn.Linear(16 * 7 * 7, 32) # 全连接层
self.fc2 = nn.Linear(32, 1) # 最终输出 1 维(用于二分类)
def forward(self, x):
x = self.pool(torch.relu(self.conv1(x))) # 28x28 -> 14x14
x = self.pool(torch.relu(self.conv2(x))) # 14x14 -> 7x7
x = x.view(-1, 16 * 7 * 7) # 扁平化张量
x = torch.relu(self.fc1(x)) # 全连接层
x = self.fc2(x) # 输出层
return x.squeeze(1) # 去除多余维度,保证输出形状一致
# 训练模型
def train(model, train_loader, criterion, optimizer, num_epochs=5):
"""训练模型"""
model.train()
for epoch in range(num_epochs):
total_loss = 0
for images, labels in train_loader:
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
total_loss += loss.item()
print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {total_loss/len(train_loader):.4f}')
# 评估模型
def test(model, test_loader):
"""测试模型,并可视化部分预测结果"""
model.eval()
correct = 0
total = 0
images_list, preds, labels_list = [], [], []
with torch.no_grad():
for images, labels in test_loader:
outputs = model(images)
predicted = (torch.sigmoid(outputs) > 0.5).float() # 通过 sigmoid 得到二分类结果
correct += (predicted == labels).sum().item()
total += labels.size(0)
images_list.extend(images.cpu())
preds.extend(predicted.cpu())
labels_list.extend(labels.cpu())
print(f'Accuracy: {100 * correct / total:.2f}%')
# 显示部分预测结果
fig, axes = plt.subplots(1, 5, figsize=(12, 3))
for i in range(5):
axes[i].imshow(images_list[i].squeeze(), cmap='gray')
axes[i].set_title(f"Pred: {int(preds[i].item())} - True: {int(labels_list[i].item())}")
axes[i].axis('off')
plt.show()
# 运行训练和测试
def main():
# 生成数据集
X_train, y_train = generate_dataset(1000)
X_test, y_test = generate_dataset(200)
# 创建数据加载器
train_dataset = Data.TensorDataset(X_train, y_train)
test_dataset = Data.TensorDataset(X_test, y_test)
train_loader = Data.DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = Data.DataLoader(test_dataset, batch_size=32, shuffle=False)
# 初始化模型、损失函数和优化器
model = CNN()
criterion = nn.BCEWithLogitsLoss() # 二元交叉熵损失
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 训练模型
train(model, train_loader, criterion, optimizer, num_epochs=5)
# 测试模型
test(model, test_loader)
if __name__ == "__main__":
main()
CNN 在 计算机视觉、医学影像、自动驾驶、遥感、NLP 和语音处理 等领域有广泛应用。其主要优势在于:
- 局部连接和权重共享,减少计算量。
- 池化层降维,增强特征提取能力。
- 适用于 2D/3D 结构数据(如图像、视频、遥感影像)
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐



所有评论(0)