LeNet图像分类-基于UCM数据集的遥感图像分类

UCM数据集

UC Merced Land-Use

UC Merced Land-Use遥感数据集是由UC Merced计算机视觉实验室公布的用于遥感图像场景分类的公开数据集,包含21类场景,具体每个类别为(1) agricultural(农田)、(2) airplane(飞机)、(3) baseball diamond(棒球内场)、(4) beach(海滩)、 (5) buildings(建筑)、(6) chaparral(灌木丛)、(7) dense residential(密集的住宅)、(8) forest(森林)、(9) freeway(高速公路,快车道)、(10) golf course(高尔夫球场)、 (11) harbor(海港)、(12) intersection(十字路口)、(13) medium residential(中等住宅)、(14) mobile home park(移动式家庭公园)、(15) overpass(立交桥)、 (16) parking lot(停车场)、 (17) river(河)、 (18) runway(跑道)、 (19) sparse residential(稀疏住宅)、 (20) storage tanks(储罐)、 (21) tennis court(网球场),其中每个类别各包含100张遥感图像,整个数据集一共2100张遥感图像,每张遥感图像的大小为256 × \times× 256。

数据集下载:UC Merced Land Use Dataset

准备好数据集后,我们开始学习吧~

1.model.py——定义LeNet网络模型。
2.train.py——加载数据集并训练,训练集计算损失值loss,测试集计算accuracy,保存训练好的网络参数。
3.predict.py——利用训练好的网络参数后,用自己找的图像进行分类测试。

1.定义LeNet网络模型---------------model.py

#-*- coding : utf-8-*-
# coding:unicode_escape
import torch.nn as nn
import torch.nn.functional as F
#在pytorch中搭建模型
#首先建立一个类,把类寄存于nn.Moudel中
class LeNet(nn.Module):
    #定义初始化函数
    def __init__(self):
        #在初始化函数中搭建需要使用的网络层结构
        super(LeNet, self).__init__()#一般涉及到多继承,就会使用super函数
        self.conv1 = nn.Conv2d(3, 16, 5)
        # 定义卷积层conv1,第一个参数就是输入特征层的深度,3表示输入的是彩色图片,使用了16个卷积核,卷积核的大小是5*5
        self.pool1 = nn.MaxPool2d(2, 2)
        #定义下采样层pool1,池化核为2*2 步长是2的最大池化操作,池化层不改变深度,只影响高度和宽度,高度宽度缩小一般
        self.conv2 = nn.Conv2d(16, 32, 5)
        # 定义第二个卷积层conv2,输入特征层的深度为16,因为第一个卷积层输出的为16的特征矩阵,采用32个卷积核,尺寸为5*5
        self.pool2 = nn.MaxPool2d(2, 2)
        # 定义第二个下采样层pool2,池化核为2*2 步长是2的最大池化操作。高度和宽度在缩小一半
        self.fc1 = nn.Linear(32*5*5, 120)
        #定义全连接层,需要将上一层输出展平也就是32*5*5,第一层的节点个数为120,
        self.fc2 = nn.Linear(120, 84)
        #第二个全连接层的输入就是上一个全连接层的输出120,第二个参数是输出
        self.fc3 = nn.Linear(84, 10)
        # 第三个全连接层的输入就是上一个全连接层的输出84,第二个参数是输出,因为是具有10个类别分类任务,所以输出是10.
    #在forward函数中定义正向传播的过程
    def forward(self, x): #x表示输入的数据
        x = F.relu(self.conv1(x))     # input(3, 32, 32) output(16, 28, 28) 16个卷积核,所以channel是16
        #进行卷积操作,在进行激活函数后输出
        x = self.pool1(x)            # output(16, 14, 14)
        #进行下采样后输出
        x = F.relu(self.conv2(x))    # output(32, 10, 10)
        #再进行卷积层核激活函数
        x = self.pool2(x)            # output(32, 5, 5)
        #再进行下采样层操作后输出
        x = x.view(-1, 32*5*5)       # output(32*5*5)
        #将特征矩阵展平使用.view函数,第一个维度进行自动推理batch设置为-1,第二个维度就是展平后的节点个数
        x = F.relu(self.fc1(x))      # output(120)
        x = F.relu(self.fc2(x))      # output(84)
        x = self.fc3(x)              # output(10)
        #全连接层3后进行输出
        return x

2.加载数据集并训练,训练集计算损失值loss,测试集计算accuracy,保存训练好的网络参数-------------------------train.py

注意:训练路径和测试路径需要改为你自己的路径。

#-*- coding : utf-8-*-
# coding:unicode_escape
import torch
import torchvision
import torch.nn as nn
from model import LeNet
import torch.optim as optim
import torchvision.transforms as transforms
#简单看一下导入的图片
#首先导入两个包
import matplotlib.pyplot as plt #绘制图像的包
import numpy as np
 
 
 
 
def main():
    transform = transforms.Compose(
        [transforms.ToTensor(),
         transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
 
    # 训练图片
    # 第一次使用时要将download设置为True才会自动去下载数据集
    train_set = torchvision.datasets.CIFAR10(root='/home/data1/ffeng_data/3.ycx/RS-SC/Image-classification/UCMerced_LandUse/train', train=True,
                                             download=True, transform=transform)
                                             #下载完成后设置为False
    # 加载训练集,实际过程需要分批次(batch)训练
    train_loader = torch.utils.data.DataLoader(train_set, batch_size=36,
                                               shuffle=True, num_workers=0)
    # shuffle=True是否将数据打乱
 
#导入测试数据集
    # 验证图片
    # 第一次使用时要将download设置为True才会自动去下载数据集
    val_set = torchvision.datasets.CIFAR10(root='/home/data1/ffeng_data/3.ycx/RS-SC/Image-classification/UCMerced_LandUse/val', train=False,
                                           download=True, transform=transform)
    val_loader = torch.utils.data.DataLoader(val_set, batch_size=10000,
                                             shuffle=False, num_workers=0)
    val_data_iter = iter(val_loader)
    #iter函数是将刚刚生成的val_loader转换为可迭代的迭代器
    val_image, val_label = val_data_iter.next()
    #转换完之后通过next()就可以得到一批数据,包含测试的图像 val_image,图像对相应的标签值val_label
 
   #把标签导入
   # UCMerced_LandUse
    CLASS = ('agricultural', 'airplane', 'baseballdiamond', 'beach', 'buildings',
             'chaparral', 'denseresidential', 'forest', 'freeway', 'golfcourse', 'harbor',
             'intersection', 'mediumresidential', 'mobilehomepark', 'overpass', 'parkinglot',
             'river', 'runway', 'sparseresidential', 'storagetanks', 'tenniscourt')
# # 使用官方的imshow(img)函数,简单看一下导入的图片
#     def imshow(img):
#        img = img / 2 + 0.5     #对图像进行反标准化处理
#        npimg = img.numpy() #将图片转化为numpy格式
#        plt.imshow(np.transpose(npimg, (1, 2, 0)))
#        plt.show() #展示出来
# # print labels
#     print(' '.join('%5s' % classes[val_label[j]] for j in range(4)))
# # show images
#     imshow(torchvision.utils.make_grid(val_image))
 
 
    #导入模型
    net = LeNet()
    loss_function = nn.CrossEntropyLoss()
    #使用Adam的优化器,第一个参数就是所需要训练的参数,学习率
    optimizer = optim.Adam(net.parameters(), lr=0.001)
 
    #进入训练过程
    for epoch in range(5):  # loop over the dataset multiple times
    #将训练集迭代5次
        running_loss = 0.0 #定义变量,用来累加训练过程中的损失
        for step, data in enumerate(train_loader, start=0):
        #通过循环遍历训练集样本
            # get the inputs; data is a list of [inputs, labels]
            inputs, labels = data #输入的图像核标签
 
            # zero the parameter gradients
            optimizer.zero_grad() #每计算一个batch就需要调用一次
            # forward + backward + optimize
            outputs = net(inputs)#将得到的输入的图片上传到网络得到输出
            loss = loss_function(outputs, labels)#通过定义的损失函数进行计算损失,第一个参数就是网络预测的值,第二个就是对应网络真实的标签
            loss.backward() #将loss进行反向传播
            optimizer.step()# 通过优化器进行更新
 
            # 接下来就是一个打印的过程
            running_loss += loss.item()
            if step % 500 == 499:    # 每隔500步打印一次数据的信息
                with torch.no_grad(): #这个函数就是再计算过程中不需要计算每个节点的损失梯度,节省空间核算力
                    outputs = net(val_image)  # [batch, 10]
                    predict_y = torch.max(outputs, dim=1)[1]#网络预测最可能是哪个类别的,再维度1上寻找最大值,最后的1只需要知道index值
                    accuracy = torch.eq(predict_y, val_label).sum().item() / val_label.size(0)
                    #最后将真实的标签按类别和预测的标签类别进行比较,再相同的地方返回1,不同就返回0,最后用一个求和操作知道本次预测对多少函数,再除以测试样本的数量就得到了准确率
                    #打印结果
                    print('[%d, %5d] train_loss: %.3f  test_accuracy: %.3f' %
                          (epoch + 1, step + 1, running_loss / 500, accuracy))
                    running_loss = 0.0
 
    print('Finished Training')
    #将模型进行保存
    save_path = './Lenet.pth'
    torch.save(net.state_dict(), save_path)
 
 
if __name__ == '__main__':
    main()

训练结束:

3.利用训练好的网络参数后,用自己找的图像进行分类-------------------------------------------predict.py

#-*- coding : utf-8-*-
# coding:unicode_escape
import torch
import torchvision.transforms as transforms
from PIL import Image
from model import LeNet
 
def main():
    transform = transforms.Compose(
        [transforms.Resize((32, 32)), #图片尺寸标准化
         transforms.ToTensor(),#将图片转化为tensor
         transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])#进行标准化处理
 
    CLASS = ('agricultural', 'airplane', 'baseballdiamond', 'beach', 'buildings',
             'chaparral', 'denseresidential', 'forest', 'freeway', 'golfcourse', 'harbor',
             'intersection', 'mediumresidential', 'mobilehomepark', 'overpass', 'parkinglot',
             'river', 'runway', 'sparseresidential', 'storagetanks', 'tenniscourt')
 
    net = LeNet() #实例化
    net.load_state_dict(torch.load('Lenet.pth')) #调用训练得到的结果
 
    im = Image.open('1.jpg') #判断这个图片
    im = transform(im)  # [C, H, W]图片标准化之后得到
    im = torch.unsqueeze(im, dim=0)  # [N, C, H, W] 再最前面增加一个维度
 
    with torch.no_grad(): #表示不需要计算梯度损失
        outputs = net(im) #输入网络图片得到输出
        predict = torch.max(outputs, dim=1)[1].numpy()
    print(CLASS[int(predict)])
    #用softmax函数处理可以得到预测该图类别
    #predict = torch.softmax(outputs, dim=1)
    #print(predict)
 
 
if __name__ == '__main__':
    main()

运行时出现报错 

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xce in position 81: invalid continuation byte

我的解决办法是:在代码首行加入下面两行代码,希望能帮到你。

#-*- coding : utf-8-*-
# coding:unicode_escape

具体参考这篇文章:Python——报错 UnicodeDecodeError: 'utf-8' codec can't decode byte 0xce in position 52: invalid continuation byte问题解决 - 小猪课堂 - 博客园 (cnblogs.com)

  • 2
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
# CNN_UCMerced-LandUse_Caffe(数据:http://vision.ucmerced.edu/datasets/landuse.html) 主要任务:基于深度学习框架完成对光学遥感图像UCMerced LandUse数据集分类。 数据特点:共包含21类土地类型图片,每类100张,每张像素大小为256*256,数据类内距离大,类间小。 完成情况:数据量太小,训练数据出现过拟合;为了克服这个问题,又减小训练时间,采用caffe框架,在别人训练好的bvlc_reference_caffenwt模型上进行fine-tune,对最后一层设置较大的学习速率,结果取得了93%的正确率;在这基础上又在fc7层上提取了每张图片的4096维特征,进行了SVM分类,取得了95%以上的分类正确率,并对结果做了可视化分析。 环境:ubuntu14.04 + caffe + python(数据划分和增强在用windows10的3.5,其余都是unbuntu下用的2.7) 程序(相关路径需要修改)/步骤: multi_divide_pic.py---多进程进行数据划分(cv2没装成功,建议用cv2,方便) multi_augmentation_pic.py---多进程数据增强 make_caffe_lmdb.py---生成caffe训练需要的数据路径文件,然后修改caffe配置文件 bvlc_reference_caffenet.caffemodel---caffe模型,在上面进行finetune(http://dl.caffe.berkeleyvision.org/?from=message&isappinstalled=1) binaryproto2npy.py---将caffe生成的均值文件转换成.npy格式 cnn_vision_caffe.py---对训练好的模型进行可视化分析 extract_features.py---获取每张图片在fc7层输出的4096维特征 svm_predict.py---使用svm对上述提取的特征进行训练预测 svm_vision.py---对svm模型进行可视化分析 tsne.py---对数据进行降维可视化

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值