神经网络学习ING——莫烦python-CNN数字识别——注解

# -*- coding:utf-8 -*-
#@Time  : 2020/6/29 22:29
#@Author: ly
import torch
import torch.nn as nn
import torch.utils.data as Data
import torchvision
import matplotlib.pyplot as plt

# Hyper Parameters
EPOCH = 1               # train the training data n times, to save time, we just train 1 epoch
BATCH_SIZE = 50
LR = 0.001              # learning rate
DOWNLOAD_MNIST = False

# Mnist digits dataset
train_data = torchvision.datasets.MNIST(
    root='./mnist/',
    train=True,                                     # this is training data
    transform=torchvision.transforms.ToTensor(),    # Converts a PIL.Image or numpy.ndarray to
                                                    # torch.FloatTensor of shape (C x H x W) and normalize in the range [0.0, 1.0]
    download=DOWNLOAD_MNIST,
)

# plot one example
#print(train_data.data.size())                 # (60000, 28, 28)
#print(train_data.targets.size())               # (60000)
# plt.imshow(train_data.data[0].numpy(), cmap='gray')
# plt.title('%i' % train_data.targets[0])
# plt.show()

# Data Loader for easy mini-batch return in training, the image batch shape will be (50, 1, 28, 28)
train_loader = Data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True)

# pick 2000 samples to speed up testing
test_data = torchvision.datasets.MNIST(root='./mnist/', train=False)
test_x = torch.unsqueeze(test_data.data, dim=1).type(torch.FloatTensor)[:2000]/255.   # shape from (2000, 28, 28) to (2000, 1, 28, 28), value in range(0,1)
test_y = test_data.targets[:2000]  #取前两千个数据

#print(test_data.data.size())                 # (10000, 28, 28)
#print(test_data.targets.size())

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        #第一层网络
        self.conv1 = nn.Sequential(         # input shape (1, 28, 28)
            nn.Conv2d(
                in_channels=1,              # input height;输入图像的通道数,灰度图像为1,RGB为3
                                            #实际卷积核个数(执行卷积运算的次数)=通道数*filters(卷积核个数)
                out_channels=16,            # n_filters
                kernel_size=5,              # filter size;卷积核的长宽
                stride=1,                   # filter movement/step;每次移动卷积核的步长
                padding=2,                  # if want same width and length of this image after Conv2d
                                            #为输入图像外围补充的‘圈数’,每一次卷积核运算的结果为一个特征值
                #卷积操作输出的形状计算公式是这样的:
                #output_size = (image_size-filter_size+2*padding)/stride + 1
            ),                              # output shape (16, 28, 28)
            nn.ReLU(),                      # activation
            nn.MaxPool2d(kernel_size=2),    # choose max value in 2x2 area, output shape (16, 14, 14)
                                            #2*2的池化,取一个做显著特征
        )
        #第二层网络
        self.conv2 = nn.Sequential(         # input shape (16, 14, 14)
            nn.Conv2d(16, 32, 5, 1, 2),     # output shape (32, 14, 14)
            nn.ReLU(),                      # activation
            nn.MaxPool2d(2),                # output shape (32, 7, 7)
        )
        #第三层,全连接层
        self.out = nn.Linear(32 * 7 * 7, 10)   # fully connected layer, output 10 classes

    def forward(self, x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = x.view(x.size(0), -1)           # flatten the output of conv2 to (batch_size, 32 * 7 * 7)
            #x.size(0)即样本x的个数=60000
            #view函数:重新改变张量的维度,参数中的-1就代表这个位置由其他位置的数字来推断(自适应y)
        output = self.out(x)  #全连接层的输入要为2维张量;规格[60000,y]
        return output, x    # return x for visualization


cnn = CNN()
#print(cnn)  # net architecture

optimizer = torch.optim.Adam(cnn.parameters(), lr=LR)   # optimize all cnn parameters
loss_func = nn.CrossEntropyLoss()                       # the target label is not one-hotted

# following function (plot_with_labels) is for visualization, can be ignored if not interested
from matplotlib import cm
try:
    from sklearn.manifold import TSNE   #TSNE:随机临近嵌入,主要用于高维数据的降维和可视化
    HAS_SK = True   #设置一个是否安装该模块的flag,给后面出图做if判断
    print(' sklearn installed ')
except:
    HAS_SK = False
    print('Please install sklearn for layer visualization')
def plot_with_labels(lowDWeights, labels):      #lowDWeights[500,2];labels[500]
    plt.cla()
    X, Y = lowDWeights[:, 0], lowDWeights[:, 1]     #2维拆成一维
    for x, y, s in zip(X, Y, labels):
        c = cm.rainbow(int(255 * s / 9)); plt.text(x, y, s, backgroundcolor=c, fontsize=9)
        #设置0-9的颜色;文本颜色及字号
    plt.xlim(X.min(), X.max()); plt.ylim(Y.min(), Y.max()); plt.title('Visualize last layer')
    plt.show()
    plt.pause(0.01)
    #设置坐标轴数字显示范围X.min(), X.max() | Y.min(), Y.max();
plt.ion()
# training and testing
for epoch in range(EPOCH):
    i = 0
    for step, (b_x, b_y) in enumerate(train_loader):   # gives batch data, normalize x when iterate train_loader
        #每次训练50个数据,样本总数为60000,step=1200
        output = cnn(b_x)[0]               # cnn output
        loss = loss_func(output, b_y)   # cross entropy loss
        optimizer.zero_grad()           # clear gradients for this training step
        loss.backward()                 # backpropagation, compute gradients
        optimizer.step()                # apply gradients
        #随着训练数据的逐步增加,网络逐渐完善,准确率上升。
        # 每50步(即每训练完2500个数据)就输入2000个测试数据输出此时网络的准确率
        #总共测试60000/2500=24次
        if step % 50 == 0:
            test_output, last_layer = cnn(test_x)   #test_output=output;last_layer=x
                                                    #经view()后的last_layer为2维张量;规格[2000,自适应1568]
            #print(test_output)
            #######
            #输出test_output为一个2000*10的张量(取的前两千个测试数据),这10列分别对应的是该测试数据集是0-9的权重
            #######
            #print(test_output.size())
            #print(last_layer.size())
            pred_y = torch.max(test_output, 1)[1].data.numpy()  #dim=1,输出test_output中每行的最大值的索引
            #print(pred_y)
            accuracy = float((pred_y == test_y.data.numpy()).astype(int).sum()) / float(test_y.size(0))
            #把索引位置等于标签的布尔值true作为整型1求和/标签总数=准确率
            i += 1
            print("第" + str(i) + "次测试其准确率:")
            print('损失: %.4f' % loss.data.numpy(), ',准确率: %.2f' % accuracy)
            if HAS_SK:
                # Visualization of trained flatten layer (T-SNE)
                tsne = TSNE(perplexity=30, n_components=2, init='pca', n_iter=5000)     #将输入数据转为2维
                plot_only = 500         #取输入数据X的前500个做可视化
                low_dim_embs = tsne.fit_transform(last_layer.data.numpy()[:plot_only, :])       # low_dim_embs规格[500,2]
                labels = test_y.numpy()[:plot_only]     #标签值
                plot_with_labels(low_dim_embs, labels)
plt.ioff()

# print 10 predictions from test data
test_output, _ = cnn(test_x[:10])
pred_y = torch.max(test_output, 1)[1].data.numpy()
print(pred_y, 'prediction number')
print(test_y[:10].numpy(), 'real number')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

橘蓝

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

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

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

打赏作者

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

抵扣说明:

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

余额充值