Pytorch入门深度学习(3)——Pytorch入门及MNIST实现(OOP)

一、Pytorch介绍

1)Pytorch介绍
PyTorch 是 Torch 在 Python 上的衍生. 因为 Torch 是一个使用 Lua 语言的神经网络库, Torch 很好用, 但是 Lua 又不是特别流行, 所有开发团队将 Lua 的 Torch 移植到了更流行的语言 Python 上.
2)Pytorch和Tensorflow
Pyrtoch最大的优点就是建立的神经网络是动态的,对比静态的TensorFlow,它能更加有效地去处理一些问题,Tensorflow 的静态计算图使得他在 RNN 上有一点点被动 (虽然它用其他途径解决了), 不过用 PyTorch 的时候, 你会对这种动态的 RNN 有更好的理解.而且 Tensorflow 的高度工业化, 它的底层代码… 你是看不懂的. PyTorch 好那么一点点, 如果你深入 API, 你至少能比看 Tensorflow 多看懂一点点 PyTorch 的底层在干嘛.

动态图:构建BP算法,首先要构建一个计算图,即网络的结构拓扑图。如构建一个三层结构,前项计算的时候把网络加到计算图里去,前项结束的时候,结构图就有了,反向传播的时候,从图的最后一层倒推,一层一层计算每一层的梯度,然后更新参数。
Tensorflow是先构建一个结构图,再对参数进行更新,不够灵活。但能分布式训练。
3)Numpy 还是Pytorch
Torch自称为神经网络界的Numpy,它能将torch产生的tensor放在GPU中加速运算,就想Numpy会把array放在CPU中加速运算。所以在神经网络中,用Torch的tensor形式更优。

import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np

# 声明一个tensor张量
a = torch.tensor(3)# 标量
print(a)
a = torch.tensor([3]) #向量
print(a)
print(type(a))
b = torch.tensor([1,2,3], dtype=torch.float32)
print(b)

a = torch.Tensor([1,2])#浮点型
print(a)
a = torch.tensor([1,2])
print(a)

a = torch.tensor([[1,2,3],[4,5,6]])
b = torch.tensor([[1,2,3],[4,5,6]])
print(a * b)
print(a + b)
print(a - b)
print(a / b)
print(torch.mm(a,b.t()))#矩阵乘法
print(torch.dot(a[0],b[0]))#求内积(torch.dot求向量的内积)

out:
tensor(3)
tensor([3])

tensor([1., 2., 3.])
tensor([1., 2.])
tensor([1, 2])
tensor([[ 1, 4, 9],
[16, 25, 36]])
tensor([[ 2, 4, 6],
[ 8, 10, 12]])
tensor([[0, 0, 0],
[0, 0, 0]])
tensor([[1, 1, 1],
[1, 1, 1]])
tensor([[14, 32],
[32, 77]])
tensor(14)
4)Pytorch是什么?
Pytorch是一个基于Python的科学计算工具包,它主要面向两种场景:
用于替代Numpy,可以使用GPU的计算力
一种深度学习研究平台,可以提供最大的灵活性和速度

x = torch.tensor([1,2])
#x.to(device="cuda")
y = torch.tensor([3,4])
if torch.cuda.is_available():
    x = x.cuda() # 把x放在GPU里面计算
    y = y.cuda()   # cpu convert cuda
    y = y.cpu() # cuda convert cpu
else:
    print(x, y)

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(type(device))
x = x.to(device)
print(x)
x.cpu()

out:
tensor([1, 2]) tensor([3, 4])

tensor([1, 2])

# numpy转torch
a = np.array([1,2,3])
b = torch.tensor([1,2,3])
c = (torch.from_numpy(a))
print(type(c))
print(type(b.numpy()))
a[0] = 5
print(c)#用的是同一套内存空间
print(torch.tensor(a))#直接转Tensor

out:


tensor([5, 2, 3], dtype=torch.int32)
tensor([5, 2, 3], dtype=torch.int32)

二、Pytorch的使用方法

1)Autograd:自动求导(automatic differentiation)
Pytorch中所有神经网络的核心是autograd包。
autograd包为张量上的所有操作提供了自动求导,它是一个运行时定义的框架,这意味着反向传播是根据你的代码如何运行来定义,并且每次迭代可以不同。
2)变量(Variable)
autograd.Variable是autograd包的核心类,它包装了张量,支持几乎所有的张量上的操作,一旦你完成前向计算,可以通过.backward()方法来自动计算所有的梯度,可以通过.data属性来访问变量中的原始张量,关于这个变量的梯度被计算放入.grad属性中

import torch
from torch.autograd import Variable

x = torch.tensor([1.,2,3], requires_grad=True)
# x = Variable(x, requires_grad=True) # 需要计算梯度
y = x.mean() # y = 1/3*(x1+x2+x3)# 只能对标量进行求导
z = y**2
w = 3*z
w.backward()

print(w)
print(z)
print(y)
print(x.grad)# 求的x的导数
print(x.data)

out:
tensor(12., grad_fn=<MulBackward0>)
tensor(4., grad_fn=<PowBackward0>)
tensor(2., grad_fn=<MeanBackward0>)
tensor([4., 4., 4.])
tensor([1., 2., 3.])

#自动求导机制
_x = [i/100 for i in range(100)]
_y = [5*i + 3 for i in _x]

w = torch.rand(1,requires_grad=True)
b = torch.rand(1,requires_grad=True)
optimizer= torch.optim.SGD([w,b],lr=0.1)

for i in range(100):
    for x,y in zip(_x, _y):
        z = w*x + b
        loss = torch.pow((z-y),2)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        print(w,b)

out:
40次以上得到
tensor([5.0000], requires_grad=True) tensor([3.0000], requires_grad=True)

四、Pytorch实现CNN

计算MNIST图片的均值和方差

import torch
from torchvision import datasets, transforms

if __name__ == '__main__':
	train_dataset = datasets.MNIST("datasets/", train=True, download=True, transform=transforms.ToTensor())
	testdataset = datasets.MNIST("datasets/", train=False, download=True, transform=transforms.ToTensor())
	dataset = train_dataset+testdataset
	dataloader = torch.utils.data.DataLoader(dataset, batch_size=70000, shuffle=True)
	data = next(iter(dataloader))[0]#通过迭代器迭代,取出来只有一个值,索引用0取出来
	mean = torch.mean(data,dim=(0,2,3))
	std = torch.std(data,dim=(0,2,3))
	print(mean)
	print(std)

out:
tensor([0.1309])
tensor([0.3084])

from torchvision import datasets, transforms
import numpy as np
if __name__ == '__main__':

	train_dataset = datasets.MNIST("datasets/", train=True, download=True, transform=transforms.ToTensor())
	testdataset = datasets.MNIST("datasets/", train=False, download=True, transform=transforms.ToTensor())
	mnist_data = train_dataset + testdataset
	_data = [d[0].data.cpu().numpy() for d in mnist_data]
	print(np.mean(_data))
	print(np.std(_data))

out:
tensor([0.1309])
tensor([0.3084])

五、Pytorch实现MNIST(OOP实现)

MyNet.py

import torch

class MLPNet(torch.nn.Module):

    def __init__(self):
        super().__init__()
        self.layer1 = torch.nn.Linear(784,128)
        self.layer2 = torch.nn.Linear(128,256)
        self.layer3 = torch.nn.Linear(256,512)
        self.layer4 = torch.nn.Linear(512,256)
        self.layer5 = torch.nn.Linear(256,128)
        self.layer6 = torch.nn.Linear(128,10)

    def forward(self, x):
        x = torch.reshape(x, (-1,784))
        x = torch.relu(self.layer1(x))
        x = torch.relu(self.layer2(x))
        x = torch.relu(self.layer3(x))
        x = torch.relu(self.layer4(x))
        x = torch.relu(self.layer5(x))
        x = self.layer6(x)#用均方差就不要用softmax
        return x

Train.py
术语:
轮次 10
迭代次数 120
batch_size
mini_batch:一个样本的泛型不广

from MyNet import MLPNet
import torch
import torch.nn.functional as F
from torchvision.datasets import MNIST
import torchvision.transforms as trans
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
from PIL import Image
import numpy as np

class Trainer:
    def __init__(self):
        self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
        self.net = MLPNet().to(self.device)
        self.loss_func = torch.nn.MSELoss()
        self.opt = torch.optim.Adam(self.net.parameters())
        self.trainset, self.testset = self.get_dataset()
    def get_dataset(self):
        transformer = trans.Compose([
            trans.ToTensor(),
            trans.Normalize((0.1309,), (0.3084,))
        ])

        trianData = MNIST(root="datasets/", train=True, download=False, transform=transformer)
        testData = MNIST(root="datasets/", train=False, download=False, transform=transformer)
        return trianData, testData

    def loader_data(self):
        trainloader = DataLoader(dataset=self.trainset, batch_size=512, shuffle=True)
        testloader = DataLoader(dataset=self.testset, batch_size=512, shuffle=True)
        return trainloader, testloader

    def train(self):
        trainloader, testloader = self.loader_data()
        losses = []
        for i in range(10):
            print("epochs:{}".format(i))
            for j, (x, y) in enumerate(trainloader):
                x = x.to(self.device)
                y = F.one_hot(y.long()).float().to(self.device)#(500,10)
                #y = torch.zeros(y.size(0),10).scatter_(1, y.view(-1, 1), 1).to(self.device)
                out = self.net(x)
                loss = self.loss_func(out, y)
                if j % 10 == 0:
                    print("{}/{},loss{}".format(j, len(trainloader), loss.float()))
                    losses.append(loss.float())
                    plt.clf()
                    plt.plot(losses)
                    plt.pause(0.01)

                self.opt.zero_grad()
                loss.backward()
                self.opt.step()

            torch.save(self.net, "models/net.pth")
            self.test(testloader)#每轮结束都测试一下

    def test(self, testloader):
        total = 0
        for x ,y in testloader:
            x = x.to(self.device)
            y = y.to(self.device)
            out = self.net(x)
            predict = torch.argmax(out, dim=1)
            total += (predict == y).sum()

        print("精确度:{}".format(total.item() / len(self.testset) * 100))

    def testPic(self):
        net = torch.load("models/net.pth")
        img = Image.open("8.jpg")
        img = trans.Resize(28)(img)
        img = trans.Grayscale()(img)
        img = trans.ToTensor()(img)
        img = 1. - img
        img = trans.Normalize((0.1309,),(0.3084,))(img)
        img = img.unsqueeze(0)
        # print(img)
        """
        但均值标准差不是0.5,归一化后不再是[-1,1],因此
        测试图片255 - 0 归一化后是 1 - 0,训练的图片是 0 - 1
        我们要测试的图片变成0 - 1,用1-img即可
        
        """
        out = net(img.to(self.device))
        print("AI的预测是:{}".format(out.argmax(dim=1)))
        # img.show()

    def testPic2(self):
        net = torch.load("models/net.pth")
        transformer = trans.Compose([
            trans.Resize(28),
            trans.CenterCrop(28),
            trans.Grayscale(),
            trans.ToTensor(),
            trans.Normalize((0.5,),(0.5,))
        ])
        """
        训练:-1黑 1 白
        测试:也要这么变,测试图片是白底黑字,训练图片是黑底白字,
        即测试图片255 - 0 归一化后是 1,-1
        训练图片0 - 255,归一化后是-1,1,所以给img.unsqueeze(0)*-1可以转化
        """
        img = transformer(Image.open("8.jpg")).unsqueeze(0)*-1
        output = net(img.to(self.device))
        print("AI的预测是:{}".format(output.argmax(dim=1)))

    def test2(self, testloader):#查看数据集
        net = torch.load("models/net.pth")
        for x ,y in testloader:
            x = x.to(self.device)
            datas = (x * 0.3084 + 0.1309) * 255
            datas = datas.cpu().numpy().astype(np.uint8)
            for i in range(x.shape[0]):
                data = datas[i].squeeze()
                out = net(x[i])
                predict = out.argmax(1)
                plt.clf()
                plt.subplot(1,2,1)
                plt.imshow(data)
                plt.subplot(1,2,2)
                plt.ylim(20)
                plt.xlim(20)
                plt.text(15,10, s="Result is :{}".format(predict.item()), color="r", fontsize=20)
                plt.pause(1)
if __name__ == '__main__':
    t = Trainer()
    train,test = t.loader_data()
    t.test2(test)
"""
self, dim, index ,value
torch.scatter()把value按照index根据dim的方向填入self中
"""
index = torch.tensor([0,2,4,1])
src = torch.zeros(4,5)
src = torch.scatter(src, dim=1, index=index.view(-1,1), value=1)
print(src)

a = F.one_hot(index)#要转long()
print(a)

out:
tensor([[1., 0., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[0., 0., 0., 0., 1.],
[0., 1., 0., 0., 0.]])
tensor([[1, 0, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 0, 1],
[0, 1, 0, 0, 0]])

你可能感兴趣的:(pytorch,深度学习,AI)