pytorch入门

第一个神经网络搭建,代码加一点注释理解

model.py

import torch.nn as nn
import torch.nn.functional as F

class LeNet(nn.Module):
    def __init__(self):
        super(LeNet,self).__init__()
        self.conv1 = nn.Conv2d(3,16,5)
        self.pool1 = nn.MaxPool2d(2,2)
        self.conv2 = nn.Conv2d(16,32,5)
        self.pool2 = nn.MaxPool2d(2,2)
        self.fc1 = nn.Linear(32*5*5,120)
        self.fc2 = nn.Linear(120,84)
        self.fc3 = nn.Linear(84,10)

    def forward(self,x):
        x = F.relu(self.conv1(x)) # input(3,32,32)
        x = self.pool1(x)  # output(16,14,14)
        x = F.relu(self.conv2(x)) # optput(32,10,10)
        x = self.pool2(x) # output(32,5,5)
        x = x.view(-1,32*5*5) # p=output(32*5*5)
        x = F.relu(self.fc1(x)) #output(120)
        x = F.relu(self.fc2(x)) # output(84)
        x = self.fc3(x) # output(10)
        return x

import torch
input1 = torch.rand([32,3,32,32])
model = LeNet()
print(model)
output = model(input1)

对cifer10 数据集的下载并进行训练   代码+注释理解

train.py

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

transform = transforms.Compose(    #  数据转换器
    [transforms.ToTensor(),  # 转换为tensor格式
     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]  # 初始化 将0-1 转化成-1~1的数据域
)
# 50000张训练图片
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,   # 封装数据 下载数据集
                                        download=False, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=36,   # 数据迭代器
                                          shuffle=True, num_workers=0)

# 这个是之前下载出现问题时,去别处扒的代码

# from torchvision.datasets import CIFAR10
# import torchvision.transforms as transforms
#
# transform = transforms.Compose(
#     [transforms.ToTensor(),
#      transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
#
# train_dataset = CIFAR10(root='.data2',
#                         train=True,
#                         transform=transform,
#                         download=True)
#
# test_dataset = CIFAR10(root='.data2',
#                        train=False,
#                        transform=transform, )
# 10000张测试图片
# 测试图片
testset = torchvision.datasets.CIFAR10(root='./data', train=False,  # 封装测试集
                                       download=False, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=10000,
                                         shuffle=False, num_workers=0)
test_data_iter = iter(testloader)
test_image, test_label = next(test_data_iter)  # next()一次性将所有的验证集提取出来

classes = ('plane', 'car', 'bird', 'cat',  # 标签
           'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
# 测试代码
# def imshow(img):
#     img = img /2+0.5 # unnormalize
#     npimg = img.numpy()
#     plt.imshow(np.transpose(npimg,(1,2,0)))
#     plt.show()
#
# # print labels
# print(' '.join('%5s'% classes[test_label[j]] for j in range(8)))
# # show images
# imshow(torchvision.utils.make_grid(test_image))
net = LeNet()
loss_function = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters(), lr=0.001)

for epoch in range(5):  # loop over the dataset multiple times 迭代五次

    running_loss = 0.0  # 累加损失函数
    for step, data in enumerate(trainloader, start=0):  # 返回数据data,还会返回data对应的步数
        # get the inputs; data is a list of [inputs,lables]
        inputs, labels = data  # 分离图像以及相对应的标签

        # zero the parameter gradients
        optimizer.zero_grad()  # 将历史损失梯度数据清零 为什么每计算一个batch,就需要用一次这个函数
        # 一次性计算多个小的batch,变相实现一个大的batch计算。 对这个梯度进行反向传播

        # forward + backward + optimize
        outputs = net(inputs)
        loss = loss_function(outputs, labels)
        loss.backward()
        optimizer.step()

        # print statistics
        running_loss += loss.item()
        if step % 500 == 499:  # print every 500 mini-batches
            with torch.no_grad():  # 这个函数非常重要,在测试和预测的工程中,必须带上这个函数,避免内存崩溃
                outputs = net(test_image)  # [batch,10]
                # 将测试训练中的batch_size 改成10000
                predict_y = torch.max(outputs, dim=1)[1]  # 0维对应的是batch 所以dim为1 是在输出的十个lables中寻找它的最大值
                # index 索引 只需要知道它的最大值的位置,并不需要的知道是多少
                accuracy = (predict_y == test_label).sum().item() / test_label.size(0)
                # 上面函数是在比较,相同的就返回True=1 不同就返回False=0
                # 在一个求和函数,就能知道在测试过程中,预测对了多少
                # item 拿到数值 / 测试样本的数目

                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)

预测脚本,自己下载了一个车的图片进行测试

 predict.pymo

import torch
import torchvision.transforms as transforms
from PIL import Image  # 图像
from model import LeNet
import numpy as np
import matplotlib.pyplot as plt
import torchvision
# 图片预处理
transforms = transforms.Compose(
    [transforms.Resize((32,32)),  # 重新缩放
     transforms.ToTensor(), # 转换格式
     transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))]) # 标准化处理

classes = ('planr','car','bird','cat',
           'deer','dog','frog','horse','ship','truck')

net = LeNet()
net.load_state_dict(torch.load('Lenet.pth')) # 载入刚刚保存的


im = Image.open('1.jpg')  # 载入图像  H W C 高 宽 深  =》 torch.tensor 格式 下一步进行图片的预处理
im = transforms(im) # [C ,H ,W]  预处理后得到的格式
im = torch.unsqueeze(im,dim=0) # [N, C, H,W]  # 加上一个维度 在零前边加一个维度 N

with torch.no_grad():  # with 上下文管理器
    outputs = net(im)  # 图像传入网络当中的到输出
    predict1 = torch.softmax(outputs,dim=1)  # 预测信息的概率分布
    predict = torch.max(outputs,dim=1)[1].data.numpy()  # 寻找输出中的最大之处对应的index 索引 ,将index传入classes中
def imshow(im):
    im = im /2+0.5 # unnormalize
    npimg = im.numpy()
    plt.imshow(np.transpose(npimg,(1,2,0)))
    plt.show()


print(predict1)  # 打印预测信息概率
print(classes[int(predict)])  # 输出lable
imshow(torchvision.utils.make_grid(im)) # 展示图片

 脚本运行结果

第二个神经网络做的是一个AlexNet

model.py

import torch.nn as nn
import torch

class AlexNet(nn.Module):
    def __init__(self,num_classes=1000,init_weights=False):
        super(AlexNet,self).__init__()
        self.features = nn.Sequential(   # feature 提取图像特征的一个结构  Sequential  将层结构打包
            nn.Conv2d(3,48,kernel_size=11,stride=4,padding=2),# input[3,224,224] output[48,55,55]
            nn.ReLU(inplace=True),  # RGB 所以通道是三。 卷积核取一半  这里的激活函数是pytorch内置的,可以增加算力降低内存占用
            nn.MaxPool2d(kernel_size=3,stride=2),  # output[48,27,27]
            nn.Conv2d(48,128,kernel_size=5,padding=2), # output[128,27,27]
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3,stride=2),  # output[128,13,13]
            nn.Conv2d(128,192,kernel_size=3,padding=1),  # output[192,13,13]
            nn.ReLU(inplace=True),
            nn.Conv2d(192,128,kernel_size=3,padding=1),  # output[128,13,13]
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3,stride=2),  # output[128,6,6]
        )
        self.classifier = nn.Sequential(  # 全连接层
            nn.Dropout(p=0.5),  # dropout 随机失活函数,防止过拟合现象  将此函数至于展平函数与全连接层之间 p=0。5失活比例
            nn.Linear(128*6*6,2048),
            nn.ReLU(inplace=True),
            nn.Dropout(p=0.5),
            nn.Linear(2048,2048),
            nn.ReLU(inplace=True),
            nn.Linear(2048,num_classes),
        )
        if init_weights:  # 初始化权重的选项 之后再定义正向传播过程
            self._initialize_weights()

    def forward(self,x):  # forward 正向传播
        x = self.features(x)  # 将训练样本输入到 features中
        x = torch.flatten(x,start_dim=1)   # 展平处理  开始维度 为一维 /展平还可以用view(x,shape[0],-1)函数
        x = self.classifier(x)  # 然后就是全连接层
        return x
    def _initialize_weights(self):  # 初始化权重函数  返回一个迭代器,遍历self。model模块  迭代网络的每一个层结构
        for m in self.modules():
            if isinstance(m,nn.Conv2d):   # 判断类别 判断层结构是否是我们给定的这个类型
                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')  # 用这个初始化方法进行权重初始化
                if m.bias is not None:  # 偏置不为空,则用零对其初始化
                    nn.init.constant_(m.bias,0)
            elif isinstance(m,nn.Linear):  # 如果传进来的是全连接层,则用normal正态分布对全连接层进行赋值
                nn.init.normal_(m.weight,0,0.01)  # 均值=0 方差=0.01
                nn.init.constant_(m.bias,0)  # 对其偏差初始化为零


 做的是一个关于花的分类 

数据集下载链接

GitHub - WZMIAOMIAO/deep-learning-for-image-processing: deep learning for image processing including classification and object-detection etc.

train.py

import torch
import torch.nn as nn
from torchvision import transforms, datasets, utils
import matplotlib.pyplot as plt
import numpy as np
import torch.optim as optim
from flower_model import AlexNet
import os
import json
import time

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")  # gpu设备使用
print(device)
#  数据预处理
data_transform = {
    "train": transforms.Compose([transforms.RandomResizedCrop(224),  # 随即裁剪 # key 为train训练集时 使用这一系列对数据进行预处理
                                 transforms.RandomHorizontalFlip(),  # 随机翻转
                                 transforms.ToTensor(),  # 转化为tensor
                                 transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]),  # 标准化处理
    "val": transforms.Compose([transforms.Resize((224, 224)),  # 对于val验证集  缩放到224 大小
                               transforms.ToTensor(),  # 转化为tensor格式
                               transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])}  # 标准化处理
data_root = os.path.abspath(
    r"C:\Users\奋斗\Desktop\deep-learning-for-image-processing-1.0 ")  # os.path.abspath(os.path.join(os.getcwd(),'../..'))  # 获取数据集所在的根目录  os.getcwd()获取挡前文件所在的目录
# os.path.join()将两个路径点连接在一起  ../.. 代表返回上上层目录
image_path = data_root + "/data_set/flower_data/"  # flower data set path
train_dataset = datasets.ImageFolder(root=image_path + "/train",  # 载入训练集数据
                                     transform=data_transform["train"])  # 数据预处理 key=train
train_num = len(train_dataset)  # 打印训练集有多少图片

# {'daisy':0, 'dandelion':1, 'rose':2, 'sunflower':3,'tulips':4}
flower_list = train_dataset.class_to_idx
cla_dict = dict((val, key) for key, val in flower_list.items())  # 将key和value反过来对应 搜索字典导出类别
# write dict into json file
json_str = json.dumps(cla_dict, indent=4)  # json. 将字典编码成json格式
with open('class_indices.json', 'w') as json_file:  # 保存一个json文件,方便在预测时读取信息
    json_file.write(json_str)

batch_size = 32
train_loader = torch.utils.data.DataLoader(train_dataset,  # 数据处理器,将训练集载入
                                           batch_size=batch_size, shuffle=True,
                                           num_workers=0)

validate_dataset = datasets.ImageFolder(root=image_path + "val",  # ImageFolder() 载入测试集 传入测试集的预处理函数
                                        transform=data_transform["val"])
val_num = len(validate_dataset)  # 打印测试集文件个数
validate_loader = torch.utils.data.DataLoader(validate_dataset,
                                              batch_size=batch_size, shuffle=True,
                                              num_workers=0)
# 测试代码
# test_data_iter = iter(validate_loader)
# test_image,test_label = next(test_data_iter)
# def imshow(img):
#     img = img/ 2+0.5 # unnormalize
#     nping = img.numpy()
#     plt.imshow(np.transpose(nping,(1,2,0)))
#     plt.show()
# print(' '.join('%5s' % cla_dict[test_label[j].item()] for j in range(4)))
# imshow(utils.make_grid(test_image))


net = AlexNet(num_classes=5, init_weights=True)

net.to(device)  # 将网络指认到gpu上
loss_function = nn.CrossEntropyLoss()  # 定义损失函数,多类别的损失交叉熵函数
# pate = list(net.parameters())  # 调试用的,查看模型的参数
optimizer = optim.Adam(net.parameters(), lr=0.0002)  # 优化器,对象是网络中所有可训练的参数 lr 学习率

save_path = './AlexNet.pth'
best_acc = 0.0  # 定义了最佳准确率 保存准确率最高的一次模型
for epoch in range(10):  # 迭代十次
    # train
    net.train()  # 调用后会启用dropout方法管理dropout方法 让其在训练中起作用而不影响预测
    running_loss = 0.0  # 定义训练中的平均损失
    t1 = time.perf_counter()  # 统计训练使用的时间
    for step, data in enumerate(train_loader, start=0):
        images, labels = data
        optimizer.zero_grad()  # 清空之前的梯度信息
        outputs = net(images.to(device))  # 开始正向传播  训练图像指认到设备上
        loss = loss_function(outputs, labels.to(device))  # 计算预测值和真实值之间的损失
        loss.backward()  # 将计算损失反向传播到每一个节点上
        optimizer.step()  # 更新每一个节点的参数

        # print statistics
        running_loss += loss.item()  # 累加
        # print train process 打印训练进度
        rate = (step + 1) / len(train_loader)  # len(train_loader)一轮需要的步数  当前训练的步数 得到进度
        a = "*" * int(rate * 50)
        b = "." * int((1 - rate) * 50)
        print("\rtrain loss: {:^3.0f}%[{}->{}]{:.3f}".format(int(rate * 100), a, b, loss), end="")

    print()
    print(time.perf_counter() - t1)  # 训练开始和训练结束相减得到的一个差值

    # validate 验证
    net.eval()  # 调用后会关闭dropout方法  管理dropout方法 让其在训练中起作用而不影响预测 还能管理batch_evalization
    acc = 0.0  # accumulate accurate number / epoch
    with torch.no_grad():  # 禁止pytorch对 参数的跟踪  在验证过程中,不会计算它的损失梯度
        for data_test in validate_loader:
            test_images, test_labels = data_test
            outputs = net(test_images.to(device))
            predict_y = torch.max(outputs, dim=1)[1]  # 预测可能性最大的那个类别
            acc += (predict_y == test_labels.to(device)).sum().item()
            # 将预测于真实的标签进行对比 对的地方为True=1  错的地方为False=0 sum=累加求和 item()获取数值
        accurate_test = acc / val_num
        if accurate_test > best_acc:
            best_acc = accurate_test
            torch.save(net.state_dict(), save_path)
        print('[epoch %d] train_loss: %.3f test_accuracy: %.3f' %
              (epoch + 1, running_loss / step, acc / val_num))
print('Finished Training')

自己找了1张图片来测试 效果可以

 命名分别为 22.jpg    这里是可以测试多张图片,建一个文件夹存放图片,使用for循环遍历文件夹进行读取;我想还可以使用多线程进行测试,改代码能力还是不够。之后提升自己能力后在进行改进。

 predict.py

import torch
from flower_model import AlexNet
from PIL import Image
from torchvision import transforms
import matplotlib.pyplot as plt
import json

data_transfrom = transforms.Compose(  # 数据处理器,将数据预处理
    [transforms.Resize((224, 224)),  # 缩放大小
     transforms.ToTensor(),  # 转换为tensor格式
     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]  # 标准化处理
)

# load image  载入图像
# img = Image.open(r"C:\Users\奋斗\Desktop\21.jpg")  # 载入图像路径
img = Image.open(r"C:\Users\奋斗\Desktop\22.jpg")
# img = Image.open(r"C:\Users\奋斗\Desktop\2.3jpg")

plt.imshow(img)  # 显示图像[H W C]
# [N,C,H,W]
img = data_transfrom(img)  # 调用图像处理器 将图像预处理 [C H W]
# expand batch dimension
img = torch.unsqueeze(img, dim=0)  # 添加维度 [N C H W] 添加batch维度

# read class_indict  读取分类字典
try:
    json_file = open('./class_indices.json', 'r')  # 读取我们保存的文件,索引对应的类别名称
    class_indict = json.load(json_file)  # 解码,转换为我们使用的字典
except Exception as e:
    print(e)
    exit(-1)

# create model
model = AlexNet(num_classes=5)  # 初始化网络,载入网络模型
# load model weight
model_weight_path = "./AlexNet.pth"
model.load_state_dict(torch.load(model_weight_path))
model.eval()  # 预测的时候,关闭掉 dropout() 方法
with torch.no_grad():  # 结束跟踪,清除梯度信息
    # print class
    output = torch.squeeze(model(img))  # 数据通过正向传播得到输出 将输出压缩 将batch维度压缩掉
    predict = torch.softmax(output, dim=0)  # 获取概率的分布
    predict_cla = torch.argmax(predict).numpy()  # 获取概率最大处的对应的索引值
print(predict)   # 打印概率分布
print(class_indict[str(predict_cla)], predict[predict_cla].item())  # 打印类别名称  以及对应的预测概率
plt.show()

测试结果

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你好

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值