【北京化工大学】 神经网络与深度学习 实验6 MATAR图像分类

本次实验使用老师发的雷达奇妙数据

实验要求

读取图像形式的MASTAR数据

1、划分数据集为test/train

2、归一化

题目1:定义并训练线性分类器的神经网络

注:本次老师的要求是不限方法,使用pytorch尽可能提升精度

1、准备函数

python 复制代码
#本文用的pycharm写的,总共四个函数,本函数要被调用所以一定要交func.py
import torch
import torch.nn as nn
from torch.utils.data import TensorDataset, DataLoader
import os
import torch.optim as optim
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt

'''
绘图
'''
def drawing(x,y,title):
    plt.plot(x,y)
    plt.title(title)
    plt.show()

'''
获取数据集
'''
def get_data(train_dir):
    train_images = []
    train_labels = []
    #对train文件夹进行遍历,读取train里面的十个文件夹,label就是文件夹名,也就是类别
    for label in os.listdir(train_dir):
        label_dir = os.path.join(train_dir, label)
        # 检查是否为文件夹
        if os.path.isdir(label_dir):
            # 遍历当前标签对应的文件夹中的所有文件
            for filename in os.listdir(label_dir):
                if filename.endswith(('.jpg')):
                    file_path = os.path.join(label_dir, filename)
                    try:
                        # 打开图像文件
                        image = Image.open(file_path)
                        # 将图像添加到训练数据列表
                        train_images.append(image)
                        # 将对应的标签添加到标签列表
                        train_labels.append(label)
                    except Exception as e:
                        print(f"读取图像 {file_path} 时出错: {e}")

    train_images = np.array(train_images)
    train_labels = np.array(train_labels)
    return train_images, train_labels

'''
进行网络的定义
'''
class net(nn.Module):
    #定义神经网络有那些层,这一部分是输入的数据
    def __init__(self):
        super().__init__()
        #三个参数矩阵和一个激活函数
        self.w1=nn.Linear(128*128, 512)#输入28*28,输出512,linear包括了局部梯度
        self.w2=nn.Linear(512, 512)
        self.w3=nn.Linear(512, 10)#输出10,10个类
        self.relu=nn.ReLU()#也不能自己写激活函数,因为也没有中间参数

    #前向传播,确定init的积木怎么摆
    def forward(self, x):
        #数据展平要不然算不了。
        #size表示该维度的大小会根据张量的总元素个数和其他指定维度的大小自动计算得出
        x = x.view(x.size(0), -1)
        x = self.w1 (x)
        x = self.relu(x)
        x = self.w2 (x)
        x = self.relu(x)
        x = self.w3 (x)
        return x

'''
使用BN方法的网络
'''
class BN(nn.Module):
    # 定义神经网络有哪些层,这一部分是输入的数据
    def __init__(self):
        super().__init__()
        # 三个参数矩阵和一个激活函数
        self.w1 = nn.Linear(128 * 128, 512)  # 输入128*128,输出512,linear包括了局部梯度
        # 在第一个全连接层后添加批量归一化层
        self.bn1 = nn.BatchNorm1d(512)
        self.w2 = nn.Linear(512, 512)
        # 在第二个全连接层后添加批量归一化层
        self.bn2 = nn.BatchNorm1d(512)
        self.w3 = nn.Linear(512, 10)  # 输出10,10个类
        self.relu = nn.ReLU()  # 也不能自己写激活函数,因为也没有中间参数

    # 前向传播,确定init的积木怎么摆
    def forward(self, x):
        # 数据展平要不然算不了。
        # size表示该维度的大小会根据张量的总元素个数和其他指定维度的大小自动计算得出
        x = x.view(x.size(0), -1)
        x = self.w1(x)
        # 在第一个全连接层输出后使用批量归一化
        x = self.bn1(x)
        x = self.relu(x)
        x = self.w2(x)
        # 在第二个全连接层输出后使用批量归一化
        x = self.bn2(x)
        x = self.relu(x)
        x = self.w3(x)
        return x

'''
加深网络
'''
class deeped_BN(nn.Module):
    def __init__(self):
        super().__init__()
        # 输入层到第一个隐藏层
        self.w1 = nn.Linear(128 * 128, 512)
        self.bn1 = nn.BatchNorm1d(512)
        # 新增隐藏层
        self.w2 = nn.Linear(512, 512)
        self.bn2 = nn.BatchNorm1d(512)
        self.w3 = nn.Linear(512, 512)
        self.bn3 = nn.BatchNorm1d(512)
        self.w4 = nn.Linear(512, 512)
        self.bn4 = nn.BatchNorm1d(512)
        # 输出层
        self.w5 = nn.Linear(512, 10)
        self.relu = nn.ReLU()

    def forward(self, x):
        # 数据展平
        x = x.view(x.size(0), -1)
        x = self.w1(x)
        x = self.bn1(x)
        x = self.relu(x)
        x = self.w2(x)
        x = self.bn2(x)
        x = self.relu(x)
        x = self.w3(x)
        x = self.bn3(x)
        x = self.relu(x)
        x = self.w4(x)
        x = self.bn4(x)
        x = self.relu(x)
        x = self.w5(x)
        return x

'''
超级加深网络
'''
class ten_deeped_BN(nn.Module):
    def __init__(self):
        super().__init__()
        # 输入层到第一个隐藏层,使用 BN
        self.w1 = nn.Linear(128 * 128, 512)
        self.bn1 = nn.BatchNorm1d(512)
        # 第二个隐藏层,使用 BN
        self.w2 = nn.Linear(512, 512)
        self.bn2 = nn.BatchNorm1d(512)

        # 后面八层不使用 BN
        self.w3 = nn.Linear(512, 512)
        self.w4 = nn.Linear(512, 512)
        self.w5 = nn.Linear(512, 512)
        self.w6 = nn.Linear(512, 512)
        self.w7 = nn.Linear(512, 512)
        self.w8 = nn.Linear(512, 512)
        self.w9 = nn.Linear(512, 512)
        self.w10 = nn.Linear(512, 512)

        # 输出层
        self.w11 = nn.Linear(512, 10)
        self.relu = nn.ReLU()

    def forward(self, x):
        # 数据展平
        x = x.view(x.size(0), -1)
        # 前两层使用 BN
        x = self.w1(x)
        x = self.bn1(x)
        x = self.relu(x)
        x = self.w2(x)
        x = self.bn2(x)
        x = self.relu(x)

        # 后面八层不使用 BN
        x = self.w3(x)
        x = self.relu(x)
        x = self.w4(x)
        x = self.relu(x)
        x = self.w5(x)
        x = self.relu(x)
        x = self.w6(x)
        x = self.relu(x)
        x = self.w7(x)
        x = self.relu(x)
        x = self.w8(x)
        x = self.relu(x)
        x = self.w9(x)
        x = self.relu(x)
        x = self.w10(x)
        x = self.relu(x)

        # 输出层
        x = self.w11(x)
        return x

'''
评估模型准确率
'''
#使用已经有的模型进行预测,torch.no_grad的意思是禁止pytorch进行梯度计算
def val_model(test_loader,dir):
    model_t = net()
    model_t.load_state_dict(torch.load(dir))
    model_t.eval()  # 将模型设置成评估模式
    correct = 0
    total = 0
    with torch.no_grad():
        for images, labels in test_loader:
            outputs = model_t(images)
            _, predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    y_acc=100*correct/total
    print(f'Accuracy on val set: {100 * correct / total}%')
    return y_acc

'''
评估BN模型准确率
'''
#使用已经有的模型进行预测,torch.no_grad的意思是禁止pytorch进行梯度计算
def valBN_model(test_loader,dir):
    model_t = BN()
    model_t.load_state_dict(torch.load(dir))
    model_t.eval()  # 将模型设置成评估模式
    correct = 0
    total = 0
    with torch.no_grad():
        for images, labels in test_loader:
            outputs = model_t(images)
            _, predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    y_acc=100*correct/total
    print(f'Accuracy on val set: {100 * correct / total}%')
    return y_acc

'''
评估加深后的BN
'''
#使用已经有的模型进行预测,torch.no_grad的意思是禁止pytorch进行梯度计算
def val_deep_BN_model(test_loader,dir):
    model_t = deeped_BN()
    model_t.load_state_dict(torch.load(dir))
    model_t.eval()  # 将模型设置成评估模式
    correct = 0
    total = 0
    with torch.no_grad():
        for images, labels in test_loader:
            outputs = model_t(images)
            _, predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    y_acc=100*correct/total
    print(f'Accuracy on val set: {100 * correct / total}%')
    return y_acc

'''
评估10层的
'''
#使用已经有的模型进行预测,torch.no_grad的意思是禁止pytorch进行梯度计算
def val_tendeep_BN_model(test_loader,dir):
    model_t = ten_deeped_BN()
    model_t.load_state_dict(torch.load(dir))
    model_t.eval()  # 将模型设置成评估模式
    correct = 0
    total = 0
    with torch.no_grad():
        for images, labels in test_loader:
            outputs = model_t(images)
            _, predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    y_acc=100*correct/total
    print(f'Accuracy on val set: {100 * correct / total}%')
    return y_acc

'''
数据增强
'''

def augment_data(images, labels):
    augmented_images = []
    augmented_labels = []
    for img, label in zip(images, labels):
        # 原始图像
        augmented_images.append(img)
        augmented_labels.append(label)

        # 水平向右平移
        shift_right = 3
        img_shifted_right = np.roll(img, shift_right, axis=1)
        img_shifted_right[:, :shift_right] = 0  # 填充空白部分为 0
        augmented_images.append(img_shifted_right)
        augmented_labels.append(label)

        # 水平向左平移
        shift_left = 3
        img_shifted_left = np.roll(img, -shift_left, axis=1)
        img_shifted_left[:, :shift_right] = 0  # 填充空白部分为 0
        augmented_images.append(img_shifted_left)
        augmented_labels.append(label)

        #翻转
        flipped_img = np.fliplr(img)
        augmented_images.append(flipped_img)
        augmented_labels.append(label)

        # 放大操作
        scale_factor = 1.2  # 放大倍数
        pil_img = Image.fromarray(img.astype(np.uint8))
        width, height = pil_img.size
        new_width = int(width * scale_factor)
        new_height = int(height * scale_factor)
        resized_img = pil_img.resize((new_width, new_height), Image.LANCZOS)

        # 将放大后的图像转换回 numpy 数组
        resized_img_np = np.array(resized_img)

        # 确保放大后的图像尺寸与原图像尺寸一致,这里简单地进行裁剪
        if resized_img_np.shape[0] > img.shape[0] and resized_img_np.shape[1] > img.shape[1]:
            start_x = (resized_img_np.shape[0] - img.shape[0]) // 2
            start_y = (resized_img_np.shape[1] - img.shape[1]) // 2
            resized_img_np = resized_img_np[start_x:start_x + img.shape[0], start_y:start_y + img.shape[1]]

        augmented_images.append(resized_img_np)
        augmented_labels.append(label)

    augmented_images = np.array(augmented_images)
    augmented_labels = np.array(augmented_labels)
    return augmented_images, augmented_labels

2、进行训练

python 复制代码
这个使用的是三层网络结构,数据增强/不增强(注意:如果直接copy这一段就是数据增强后的,不增强的话自己注释就好了),使用的最垃圾的归一化直接除以255
from fuc import *
'''
读取数据
'''
#读取训练集
train_img,train_label=get_data('mstar/mstar/train')
#构建一个标签到整数的映射,然后把标签转换为整数。。因为标签不是传统的数字,所以这么搞
#第一步先对标签进行排序
sorted_label=sorted(set(train_label))
#第二步生成mapping,这样生成对应的他妈的标签就不会是随机的。
label_mapping = {label: idx for idx, label in enumerate(sorted_label)}
train_labels = np.array([label_mapping[label] for label in train_label])
print(f"训练集数量: {len(train_img)}")
#因为是他娘的灰度图像所以就是只有两个维度
height,wid=train_img[0].shape
print(f"训练集图片维度:{wid},{height}")
print(f"训练集标签的样子:{train_labels}")

#读取验证集
val_img,val_label=get_data('mstar/mstar/validation')
val_labels = np.array([label_mapping[label] for label in val_label])
print(f"验证集数量: {len(val_img)}")
height,wid=val_img[0].shape
print(f"验证集维度:{wid},{height}")
print(f"验证集标签的样子:{val_labels}")

# '''
# 这部分进行数据增强,不增强直接注释
# '''
# train_img,train_label=augment_data(train_img,train_label)
# #这里要重新构建mapping,因为增强了数据
# sorted_label=sorted(set(train_label))
# label_mapping = {label: idx for idx, label in enumerate(sorted_label)}
# train_labels = np.array([label_mapping[label] for label in train_label])
# print(f"增强后的训练集数量: {len(train_img)}")
# height,wid=train_img[0].shape
# print(f"增强后的训练集图片维度:{wid},{height}")
# print(f"增强后训练集标签的样子:{train_labels}")

'''
开始准备训练
'''
model=net()
# 数据预处理
# 转换为 PyTorch 张量并调整维度,指定张量的数据类型是32的浮点数
train_images = torch.tensor(train_img, dtype=torch.float32).unsqueeze(1) / 255.0
train_labels = torch.tensor(train_labels, dtype=torch.long)
test_images = torch.tensor(val_img, dtype=torch.float32).unsqueeze(1) / 255.0
test_labels = torch.tensor(val_labels, dtype=torch.long)

# 创建数据集和数据加载器
train_dataset = TensorDataset(train_images, train_labels)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_dataset = TensorDataset(test_images, test_labels)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
#optim是pytorch的优化算法模块,model.parameter返回模型中所有需要学习的参数
optimizer = optim.Adam(model.parameters(), lr=0.001)
y_loss=[]#记录损失来画图


'''
训练模型
'''
x_row=[]
y_acc=[]
num_epochs = 30
for epoch in range(num_epochs):
    x_row.append(epoch+1)
    #把模型调整成训练模式
    model.train()
    #初始化损失
    running_loss = 0.0
    #遍历train_loader的每一个批次数据
    #注:enumerate是将一个可迭代对象组合为一个带索引的枚举对象,可以同时获得索引和对应的值。在这个项目中就是获取图像和标签
    for i, (images, labels) in enumerate(train_loader):
        #把优化器中梯度清零,否则梯度会累计
        optimizer.zero_grad()
        #将数据丢到模型里得到输出
        outputs = model(images)
        #计算损失,criterion前面定义了,是交叉熵损失
        loss = criterion(outputs, labels)
        #反向传播
        loss.backward()
        #根据得到的梯度,使用优化器(前面定义了是Adam)更新模型参数
        optimizer.step()
        # 这里的loss相当于一个类,用loss.item把loss的值取出来
        running_loss += loss.item()
    #这个y_loss是一个数组,前面定义了,用于后面的画图
    y_loss.append(running_loss / len(train_loader))
    #这个函数在前面定义了,用于评测准确率
    torch.save(model.state_dict(),'model_training....pth')
    print('success saved tempmodel')
    y=val_model(test_loader,'model_training....pth')
    y_acc.append(y)
    print(f'Epoch {epoch + 1}/{num_epochs}, Loss: {running_loss / len(train_loader)}')
torch.save(model.state_dict(),'for_nothing_model.pth')
drawing(x_row,y_loss,'loss_img')
drawing(x_row,y_acc,'acc_img')

未进行数据增强

数据增强后

3、今天新学的BN方法,因为BN方法在求均值和方差不准确所以相当于随机加上了噪声,所以使用BN方法就不用正则化了

python 复制代码
from fuc import *
'''
读取数据
'''
#读取训练集
train_img,train_label=get_data('mstar/mstar/train')
#构建一个标签到整数的映射,然后把标签转换为整数。。因为标签不是传统的数字,所以这么搞
#第一步先对标签进行排序
sorted_label=sorted(set(train_label))
#第二步生成mapping,这样生成对应的他妈的标签就不会是随机的。
label_mapping = {label: idx for idx, label in enumerate(sorted_label)}
train_labels = np.array([label_mapping[label] for label in train_label])
print(f"训练集数量: {len(train_img)}")
#因为是他娘的灰度图像所以就是只有两个维度
height,wid=train_img[0].shape
print(f"训练集图片维度:{wid},{height}")
print(f"训练集标签的样子:{train_labels}")

#读取验证集
val_img,val_label=get_data('mstar/mstar/validation')
val_labels = np.array([label_mapping[label] for label in val_label])
print(f"验证集数量: {len(val_img)}")
height,wid=val_img[0].shape
print(f"验证集维度:{wid},{height}")
print(f"验证集标签的样子:{val_labels}")

'''
这部分进行数据增强,不增强直接注释
'''
train_img,train_label=augment_data(train_img,train_label)
#这里要重新构建mapping,因为增强了数据
sorted_label=sorted(set(train_label))
label_mapping = {label: idx for idx, label in enumerate(sorted_label)}
train_labels = np.array([label_mapping[label] for label in train_label])
print(f"增强后的训练集数量: {len(train_img)}")
height,wid=train_img[0].shape
print(f"增强后的训练集图片维度:{wid},{height}")
print(f"增强后训练集标签的样子:{train_labels}")

'''
开始准备训练
'''
model=BN()
# 数据预处理
# 转换为 PyTorch 张量并调整维度,指定张量的数据类型是32的浮点数
train_images = torch.tensor(train_img, dtype=torch.float32).unsqueeze(1) / 255.0
train_labels = torch.tensor(train_labels, dtype=torch.long)
test_images = torch.tensor(val_img, dtype=torch.float32).unsqueeze(1) / 255.0
test_labels = torch.tensor(val_labels, dtype=torch.long)

# 创建数据集和数据加载器
train_dataset = TensorDataset(train_images, train_labels)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_dataset = TensorDataset(test_images, test_labels)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
#optim是pytorch的优化算法模块,model.parameter返回模型中所有需要学习的参数
optimizer = optim.Adam(model.parameters(), lr=0.001)
y_loss=[]#记录损失来画图


'''
训练模型
'''
x_row=[]
y_acc=[]
num_epochs = 30
for epoch in range(num_epochs):
    x_row.append(epoch+1)
    #把模型调整成训练模式
    model.train()
    #初始化损失
    running_loss = 0.0
    #遍历train_loader的每一个批次数据
    #注:enumerate是将一个可迭代对象组合为一个带索引的枚举对象,可以同时获得索引和对应的值。在这个项目中就是获取图像和标签
    for i, (images, labels) in enumerate(train_loader):
        #把优化器中梯度清零,否则梯度会累计
        optimizer.zero_grad()
        #将数据丢到模型里得到输出
        outputs = model(images)
        #计算损失,criterion前面定义了,是交叉熵损失
        loss = criterion(outputs, labels)
        #反向传播
        loss.backward()
        #根据得到的梯度,使用优化器(前面定义了是Adam)更新模型参数
        optimizer.step()
        # 这里的loss相当于一个类,用loss.item把loss的值取出来
        running_loss += loss.item()
    #这个y_loss是一个数组,前面定义了,用于后面的画图
    y_loss.append(running_loss / len(train_loader))
    #这个函数在前面定义了,用于评测准确率
    torch.save(model.state_dict(),'model_training....pth')
    print('success saved tempmodel')
    y=valBN_model(test_loader,'model_training....pth')
    y_acc.append(y)
    print(f'Epoch {epoch + 1}/{num_epochs}, Loss: {running_loss / len(train_loader)}')
torch.save(model.state_dict(),'BN_augment_model.pth')
drawing(x_row,y_loss,'loss_img')
drawing(x_row,y_acc,'acc_img')

BN方法加上数据增强

python 复制代码
from fuc import *
'''
读取数据
'''
#读取训练集
train_img,train_label=get_data('mstar/mstar/train')
#构建一个标签到整数的映射,然后把标签转换为整数。。因为标签不是传统的数字,所以这么搞
#第一步先对标签进行排序
sorted_label=sorted(set(train_label))
#第二步生成mapping,这样生成对应的他妈的标签就不会是随机的。
label_mapping = {label: idx for idx, label in enumerate(sorted_label)}
train_labels = np.array([label_mapping[label] for label in train_label])
print(f"训练集数量: {len(train_img)}")
#因为是他娘的灰度图像所以就是只有两个维度
height,wid=train_img[0].shape
print(f"训练集图片维度:{wid},{height}")
print(f"训练集标签的样子:{train_labels}")

#读取验证集
val_img,val_label=get_data('mstar/mstar/validation')
val_labels = np.array([label_mapping[label] for label in val_label])
print(f"验证集数量: {len(val_img)}")
height,wid=val_img[0].shape
print(f"验证集维度:{wid},{height}")
print(f"验证集标签的样子:{val_labels}")

'''
这部分进行数据增强,不增强直接注释
'''
train_img,train_label=augment_data(train_img,train_label)
#这里要重新构建mapping,因为增强了数据
sorted_label=sorted(set(train_label))
label_mapping = {label: idx for idx, label in enumerate(sorted_label)}
train_labels = np.array([label_mapping[label] for label in train_label])
print(f"增强后的训练集数量: {len(train_img)}")
height,wid=train_img[0].shape
print(f"增强后的训练集图片维度:{wid},{height}")
print(f"增强后训练集标签的样子:{train_labels}")

'''
开始准备训练
'''
model=deeped_BN()
# 数据预处理
# 转换为 PyTorch 张量并调整维度,指定张量的数据类型是32的浮点数
train_images = torch.tensor(train_img, dtype=torch.float32).unsqueeze(1) / 255.0
train_labels = torch.tensor(train_labels, dtype=torch.long)
test_images = torch.tensor(val_img, dtype=torch.float32).unsqueeze(1) / 255.0
test_labels = torch.tensor(val_labels, dtype=torch.long)

# 创建数据集和数据加载器
train_dataset = TensorDataset(train_images, train_labels)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_dataset = TensorDataset(test_images, test_labels)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
#optim是pytorch的优化算法模块,model.parameter返回模型中所有需要学习的参数
optimizer = optim.Adam(model.parameters(), lr=0.001)
y_loss=[]#记录损失来画图


'''
训练模型
'''
x_row=[]
y_acc=[]
num_epochs = 30
for epoch in range(num_epochs):
    x_row.append(epoch+1)
    #把模型调整成训练模式
    model.train()
    #初始化损失
    running_loss = 0.0
    #遍历train_loader的每一个批次数据
    #注:enumerate是将一个可迭代对象组合为一个带索引的枚举对象,可以同时获得索引和对应的值。在这个项目中就是获取图像和标签
    for i, (images, labels) in enumerate(train_loader):
        #把优化器中梯度清零,否则梯度会累计
        optimizer.zero_grad()
        #将数据丢到模型里得到输出
        outputs = model(images)
        #计算损失,criterion前面定义了,是交叉熵损失
        loss = criterion(outputs, labels)
        #反向传播
        loss.backward()
        #根据得到的梯度,使用优化器(前面定义了是Adam)更新模型参数
        optimizer.step()
        # 这里的loss相当于一个类,用loss.item把loss的值取出来
        running_loss += loss.item()
    #这个y_loss是一个数组,前面定义了,用于后面的画图
    y_loss.append(running_loss / len(train_loader))
    #这个函数在前面定义了,用于评测准确率
    torch.save(model.state_dict(),'model_training....pth')
    print('success saved tempmodel')
    y=val_deep_BN_model(test_loader,'model_training....pth')
    if epoch>10 and y>y_acc[epoch-1] :
        #今天问过老师了,损失是用于训练过程中对训练进行诊断的,判断代码有没有写错。同时由于BN会随机给数据增加噪声,所以可以保存最好的模型
        torch.save(model.state_dict(), 'best_10deeped_BN_augment_model.pth')
    y_acc.append(y)
    print(f'Epoch {epoch + 1}/{num_epochs}, Loss: {running_loss / len(train_loader)}')
torch.save(model.state_dict(),'deeped_BN_augment_model.pth')
drawing(x_row,y_loss,'loss_img')
drawing(x_row,y_acc,'acc_img')

加深后的

4、超级加深,变成十层

python 复制代码
from fuc import *
'''
读取数据
'''
#读取训练集
train_img,train_label=get_data('mstar/mstar/train')
#构建一个标签到整数的映射,然后把标签转换为整数。。因为标签不是传统的数字,所以这么搞
#第一步先对标签进行排序
sorted_label=sorted(set(train_label))
#第二步生成mapping,这样生成对应的他妈的标签就不会是随机的。
label_mapping = {label: idx for idx, label in enumerate(sorted_label)}
train_labels = np.array([label_mapping[label] for label in train_label])
print(f"训练集数量: {len(train_img)}")
#因为是他娘的灰度图像所以就是只有两个维度
height,wid=train_img[0].shape
print(f"训练集图片维度:{wid},{height}")
print(f"训练集标签的样子:{train_labels}")

#读取验证集
val_img,val_label=get_data('mstar/mstar/validation')
val_labels = np.array([label_mapping[label] for label in val_label])
print(f"验证集数量: {len(val_img)}")
height,wid=val_img[0].shape
print(f"验证集维度:{wid},{height}")
print(f"验证集标签的样子:{val_labels}")

'''
这部分进行数据增强,不增强直接注释
'''
train_img,train_label=augment_data(train_img,train_label)
#这里要重新构建mapping,因为增强了数据
sorted_label=sorted(set(train_label))
label_mapping = {label: idx for idx, label in enumerate(sorted_label)}
train_labels = np.array([label_mapping[label] for label in train_label])
print(f"增强后的训练集数量: {len(train_img)}")
height,wid=train_img[0].shape
print(f"增强后的训练集图片维度:{wid},{height}")
print(f"增强后训练集标签的样子:{train_labels}")

'''
开始准备训练
'''
model=deeped_BN()
# 数据预处理
# 转换为 PyTorch 张量并调整维度,指定张量的数据类型是32的浮点数
train_images = torch.tensor(train_img, dtype=torch.float32).unsqueeze(1) / 255.0
train_labels = torch.tensor(train_labels, dtype=torch.long)
test_images = torch.tensor(val_img, dtype=torch.float32).unsqueeze(1) / 255.0
test_labels = torch.tensor(val_labels, dtype=torch.long)

# 创建数据集和数据加载器
train_dataset = TensorDataset(train_images, train_labels)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_dataset = TensorDataset(test_images, test_labels)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
#optim是pytorch的优化算法模块,model.parameter返回模型中所有需要学习的参数
optimizer = optim.Adam(model.parameters(), lr=0.001)
y_loss=[]#记录损失来画图


'''
训练模型
'''
x_row=[]
y_acc=[]
num_epochs = 30
for epoch in range(num_epochs):
    x_row.append(epoch+1)
    #把模型调整成训练模式
    model.train()
    #初始化损失
    running_loss = 0.0
    #遍历train_loader的每一个批次数据
    #注:enumerate是将一个可迭代对象组合为一个带索引的枚举对象,可以同时获得索引和对应的值。在这个项目中就是获取图像和标签
    for i, (images, labels) in enumerate(train_loader):
        #把优化器中梯度清零,否则梯度会累计
        optimizer.zero_grad()
        #将数据丢到模型里得到输出
        outputs = model(images)
        #计算损失,criterion前面定义了,是交叉熵损失
        loss = criterion(outputs, labels)
        #反向传播
        loss.backward()
        #根据得到的梯度,使用优化器(前面定义了是Adam)更新模型参数
        optimizer.step()
        # 这里的loss相当于一个类,用loss.item把loss的值取出来
        running_loss += loss.item()
    #这个y_loss是一个数组,前面定义了,用于后面的画图
    y_loss.append(running_loss / len(train_loader))
    #这个函数在前面定义了,用于评测准确率
    torch.save(model.state_dict(),'model_training....pth')
    print('success saved tempmodel')
    y=val_deep_BN_model(test_loader,'model_training....pth')
    if epoch>10 and y>y_acc[epoch-1] :
        #今天问过老师了,损失是用于训练过程中对训练进行诊断的,判断代码有没有写错。同时由于BN会随机给数据增加噪声,所以可以保存最好的模型
        torch.save(model.state_dict(), 'best_10deeped_BN_augment_model.pth')
    y_acc.append(y)
    print(f'Epoch {epoch + 1}/{num_epochs}, Loss: {running_loss / len(train_loader)}')
torch.save(model.state_dict(),'deeped_BN_augment_model.pth')
drawing(x_row,y_loss,'loss_img')
drawing(x_row,y_acc,'acc_img')

发现结果并没有变得很好。这个应该是没有过拟合风险的,因为损失其实比五层高,

5、把所有的结果集合一下吧(兄弟们可以不用写这个,写这个只是展示结果)

python 复制代码
import torch
import torch.nn as nn
import numpy as np
from fuc import get_data
from torch.utils.data import TensorDataset, DataLoader
from fuc import net,BN,deeped_BN,val_model,valBN_model,val_deep_BN_model,val_tendeep_BN_model,ten_deeped_BN

'''
获取数据
'''
val_img,val_label=get_data('mstar/mstar/validation')
sorted_label=sorted(set(val_label))
#标签对应
label_mapping = {label: idx for idx, label in enumerate(sorted_label)}
train_labels = np.array([label_mapping[label] for label in val_label])
val_labels = np.array([label_mapping[label] for label in val_label])
#验证一下该死的标签有没有对应上
print(f"验证集数量: {len(val_img)}")
height,wid=val_img[0].shape
print(f"验证集维度:{wid},{height}")
print(f"验证集标签的样子:{val_labels}")
test_images = torch.tensor(val_img, dtype=torch.float32).unsqueeze(1) / 255.0
test_labels = torch.tensor(val_labels, dtype=torch.long)
test_dataset = TensorDataset(test_images, test_labels)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)

#/255归一化,未数据增强,三层网络
model=net()
print("#/255归一化,未数据增强,三层网络")
y=val_model(test_loader,'for_nothing_model.pth')
#/255归一化,数据增强,三层网络
print("#/255归一化,数据增强,三层网络")
y=val_model(test_loader,'augumented_data_model.pth')

#BN方法,数据增强,三层网络
model=BN()
print("#BN方法,数据增强,三层网络")
y=valBN_model(test_loader,'BN_augment_model.pth')

#BN方法,数据增强,5层网络
model=deeped_BN()
print('#BN方法,数据增强,5层网络')
y=val_deep_BN_model(test_loader,'best_deeped_BN_augment_model.pth')

#十层网络。前两层BN
model=ten_deeped_BN()
print('十层网络。前两层BN')
y=val_tendeep_BN_model(test_loader,'best_10deeped_BN_augment_model.pth')

这个就是结果了,最好就到98%,孩子想不出办法了。

相关推荐
还不秃顶的计科生16 分钟前
具身智能论文学习8:Octo: An Open-Source Generalist Robot Policy
人工智能·深度学习·学习·机器学习·语言模型·vla·vlm
新知图书26 分钟前
6.4 关键时刻:它自己修好了 Bug
人工智能·agent·ai agent·智能体
深海鱼在掘金1 小时前
深入浅出RAG——第7章:基础篇实战:文档问答机器人
人工智能·typescript·命令行
Jay80591 小时前
一文讲清楚 Epoch、Batch 和 Iteration 的区别
人工智能
深海鱼在掘金1 小时前
深入浅出RAG——第8章:RAG 的局限性及应对策略
人工智能·架构
lucas_AI1 小时前
1.2B 小模型赢过 235B 大模型:NaviDC-OCR 把文档解析卷明白了
人工智能·深度学习·算法
阿星AI工作室1 小时前
一文看懂爆火的 Graph Engineering,以及它和 Loop Engineering、Agent 循环到底啥关系
人工智能
杀生丸学AI1 小时前
【稀疏重建】StructSplat:基于非校准稀疏视图的可泛化3DGS
深度学习·3d·音视频·transformer·三维重建·空间智能
小柯南敲键盘1 小时前
跨境电商图片翻译工具推荐:批量AI翻译+视频字幕+智能抠图
人工智能·python·音视频
王六米。1 小时前
武汉人工智能应用软件开发、企业AI智能体服务怎么排查
人工智能·武汉自动意志科技有限公司·智钳claw·ai漫剧生成·人工智能应用软件开发·企业ai智能体服务