CNN卷积LeNet-5 分类小案例(办公室位置识别)

项目git 代码:

        https://github.com/Boris-2021/Location_awareness-.git


流程图架构图

 数据集的收集

  1. 分五类地点:
    1. 正门口前台前廊道。
    2. 男厕所门前。
    3. 资料室门前廊道。
    4. 会议室门前廊道。
    5. 办公室B区门前廊道。

  1. 收集数量计划:
    1. 站立姿势竖直拍摄方向
    2. 一点365度,50张照片
    3. 5点共250张照片
    4. 一个地点一个数据集文件夹

 数据处理及拆分

创建图像处理类:

class RMB_dataset(Dataset):
    def __init__(self, path="", transform=None):
        # 输入:图像的存储位置
        # 负责:根据指定的路径 将训练集 or 测试集 or 验证集 组织成如下形式
        # train_data = [[图像名称1, 类别1],[图像名称2, 类别2],....[图像名称n, 类别n]]
        self.img_info = []
        for root, dir, files in os.walk(path):
            for file in files:
                file_name = os.path.join(root, file)
                label = int(file_name.split('\\')[-2])
                # print(file_name)
                # 0: '办公室B区门前廊道', 1: '会议室门前廊道', 2: '男厕所门前', 3: '正门口前台前廊道', 4: '资料室门前廊道'
                self.img_info.append([file_name, label])
        self.transfrom = transform

    # def __getitem__(self, item):

    def __getitem__(self, index):
        # 逐张读取图像
        # 之后进行图像处理:旋转、缩放、模糊,翻转
        # index 是个下标。范围【0,训练集的长度)
        img_name, label = self.img_info[index]  # 读图像

        img = Image.open(img_name)  # image mode=RGB size=3468x4624

        if self.transfrom is not None:
            img = self.transfrom(img)

        return img, label

    def __len__(self):
        # 返回值是整个数据集的长度
        return len(self.img_info)

        该类及方法得作用是将图像像素点得RGB值,加载为网络可以输入得数据格式。[[图像1, 类别1],[图像2, 类别2],....[图像n, 类别n]]。

计算图像集合中图像RGB值得均差,标准差方法:

# 计算数据集的均值和标准差
def getStat(train_data):
    '''
    Compute mean and variance for training data
    :param train_data: 自定义类Dataset(或ImageFolder即可)
    :return: (mean, std)
    '''
    print('Compute mean and variance for training data.')
    print(len(train_data))
    train_loader = torch.utils.data.DataLoader(
        train_data, batch_size=1, shuffle=False, num_workers=0,
        pin_memory=True)
    mean = torch.zeros(3)
    std = torch.zeros(3)
    for X, _ in train_loader:
        for d in range(3):
            mean[d] += X[:, d, :, :].mean()
            std[d] += X[:, d, :, :].std()
    mean.div_(len(train_data))
    std.div_(len(train_data))
    return list(mean.numpy()), list(std.numpy())

        将数据集得目录输入进方法,得到数据集得mean及std。norm_std = [0.211, 0.223, 0.237],norm_mean = [0.472, 0.456, 0.425]。

transform模块将图像4维numpy矩阵进行缩放,灰度,归一化处理。

# 仅在训练集中增加大量的图像处理,灰度处理
trans_train = transforms.Compose([
    transforms.Resize((Image_size, Image_size,)),  # 缩放图像
    transforms.RandomGrayscale(p=0.9),  # 90%的数据灰度化
    transforms.ToTensor(),  # 将图像转换为tensor, 除255
    transforms.Normalize(norm_mean, norm_std)  # 归一化
])

最终得转化为网络可用得数据格式得图像数据,打乱分批(batch)神经网路模型一个批次一个批次得训练。

# 针对训练集
train_path = "dataset/train"
train_data = RMB_dataset(path=train_path, transform=trans_train)

train_loader = DataLoader(
    dataset=train_data,  # 数据类的对象
    batch_size=Batch_size,
    shuffle=True,
    # num_workers=1

        Batch_size = 20 每二十个图像数据为一个批次。

模型的建立(LeNet-5)

        参考 https://blog.csdn.net/qq_42570457/article/details/81460807

使用pytorch模块建立网络结构:

# 网络结构
# 基本定义__init__, 前向传播forward
class LeNet(nn.Module):
    def __init__(self, classes):
        # 初始化函数中,定义每层
        super(LeNet, self).__init__()
        # 输入的通道数3,输出的通道数6,卷积核的宽和高都是5
        # 卷积核:6*3*5*5
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.conv2 = nn.Conv2d(6, 16, 5)  # 卷积核 16*6*5*5
        self.fc1 = nn.Linear(16*13*13, 120)  # 全连接
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, classes)
        self.relu = nn.ReLU(inplace=True)

    def forward(self, x):
        # X: B*C*H*W
        # X: 1*3*64*64
        out = F.relu(self.conv1(x))  # 1*6*64*64
        out = F.max_pool2d(out, 2)  # 核的大小2*2; 1*6*60*60
        out = F.relu(self.conv2(out))  # 1* 16*30*30
        out = F.max_pool2d(out, 2)  # 核的大小2*2;1*16*26*26
        out = out.view(out.size(0), -1)  # 展平(1, 16*13*13)==(1, 2704)
        out = F.relu(self.fc1(out))  # full connect  (1, 120)
        out = F.relu(self.fc2(out))  # (1, 84)
        out = self.fc3(out)  # (1, 类别数)
        return out

网络识别图片过程:

        LeNet-5是一个较简单的卷积神经网络。下图显示了其结构:输入的二维图像,先经过两次卷积层到池化层,再经过全连接层,最后输出层。

各层参数详解:

1)INPUT层-输入层,首先是数据 INPUT 层,输入图像的尺寸统一缩放并归一化为64*64。

2)conv1卷积层:      

        输入图片:64*64

        卷积核大小:5*5

        卷积核种类:6

        输出featuremap大小:60*60 (64-5+1)=60

        神经元数量:60*60*6

        可训练参数:(5*5+1) * 6(每个滤波器5*5=25个unit参数和一个bias参数,一共6个滤波器)

        连接数:(5*5+1)*6*60*60=129600

3)max_pool2d池化层:

        输入:60*60

        采样区域:2*2

        采样方式:4个输入相加,乘以一个可训练参数,再加上一个可训练偏置。

        采样种类:6

        输出featureMap大小:30*30(60/2)

        神经元数量:30*30*6

        可训练参数:2*6(和的权+偏置)

        连接数:(2*2+1)*6*30*30

        S2中每个特征图的大小是C1中特征图大小的1/4。

4)conv2卷积层:

        输入:30*30

        卷积核大小:5*5

        卷积核种类:16

        输出featureMap大小:26*26 (30-5+1)=26

        神经元数量:26*26*16

        可训练参数:(5*5+1) * 6(每个滤波器5*5=25个unit参数和一个bias参数,一共6个滤波器)

        连接数:(5*5+1)*6*26*26

5) max_pool2d池化层:

        输入:26*26

        采样区域:2*2

        采样方式:4个输入相加,乘以一个可训练参数,再加上一个可训练偏置。

        采样种类:16

        输出featureMap大小:13*13(26/2)

        神经元数量:13*13*6

        可训练参数:2*16(和的权+偏置)

        连接数:(2*2+1)*6*13*13

        S2中每个特征图的大小是C1中特征图大小的1/4。

6)fc1全连接层:

        输入:16*13*13 = (1, 2704)

        计算方式:计算输入向量和权重向量之间的点积,再加上一个偏置。

        可训练参数:120*( 2704+1)

        输出:(1,120)

7)Fc2全连接层:

        输入:(1,120)

        计算方式:计算输入向量和权重向量之间的点积,再加上一个偏置。

        可训练参数:84*( 120+1)

        输出:84

8)Fc2全连接层:

        84==>5

 模型的训练过程

  1. 设置超参数:

        max_epochs = 30 表示样集训练30轮。

        LR = 0.01 初始学习率0.01。

        Batch_size = 20 一批20个样本。

        Image_size = 64 图片缩放尺寸64。

  1. loss_fun = nn.CrossEntropyLoss() 使用交叉熵损失函数。
  2. optimizer = Adam(model.parameters(), lr=LR) 梯度下降方法ADAM,牛顿法的一种升级方法,可以尽快的达到收敛效果。
  3. 保存模型:
if len(acc_rate_list) > 2 and acc_rate > acc_rate_list[-2]:
    # 保存模型
    torch.save(model.state_dict(), 'model/location.pth')

        保证了模型保存准确率最高的那一个。

 结果展示

预测方法:

def predicted(img_name):
    img = Image.open(img_name).convert('RGB')
    norm_mean = [0.472, 0.456, 0.425]
    norm_std = [0.211, 0.223, 0.237]

    img = F.resize(img, size=(64, 64))  # 缩放
    img = F.to_tensor(img).to(device)
    img = F.normalize(img, norm_mean, norm_std)
    # print(img)
    # print(img.shape)
    # 将图片扩展为四维

    img = img.expand(1, 3, 64, 64)
    # print(img)
    # print(img.shape)

    output = model(img)
    _, y_pred = torch.max(output, dim=1)
    y_pred = y_pred.data.cpu().numpy()[0]
    transition_dict = {0: '办公室B区门前廊道', 1: '会议室门前廊道', 2: '男厕所门前', 3: '正门口前台前廊道', 4: '资料室门前廊道'}
    pred_location = transition_dict[y_pred]  # 转化为位置信息

    org_img = Image.open(img_name)
    plt.imshow(org_img)
    plt.title(pred_location)
    plt.show()

         将想要预测的图像路径传如预测方法。得到预测结果。

 

 目前模型训练30轮,在测试集中现实的准确率达到80%左右。

项目git 代码:

        https://github.com/Boris-2021/Location_awareness-.git

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值