Bootstrap

MXNet学习——自定义工具包

目前正在看《动手学深度学习》 ,这里是书中建议的部分工具包内容,内容持续更新中……

# -------------------------------------------------------------------------------
# Description:  
# Reference:
# Author: Sophia
# Date:   2021/2/23
# -------------------------------------------------------------------------------
from IPython import display
from mxnet import autograd, nd, init, gluon
from mxnet.gluon import data as gdata, loss as gloss, nn
import random, sys, time, matplotlib.pyplot as plt, mxnet as mx, os


# 定义模型(线性回归)
def linear_regression(X, w, b):
    return nd.dot(X, w) + b


# 定义平方损失函数
def squared_loss(yhat, y):
    return (yhat - y.reshape(yhat.shape)) ** 2 / 2


# 用矢量图显示
def use_svg_display():  # SVG: 可缩放矢量图形(Scalable Vector Graphics)
    display.set_matplotlib_formats('svg')


# 设置图的尺寸
def set_figsize(figsize=(3.5, 2.5)):
    use_svg_display()
    plt.rcParams['figure.figsize'] = figsize


# 数值标签 -> 文本标签
def get_fashion_mnist_labels(labels):
    text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat',
                   'sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']
    return [text_labels[int(i)] for i in labels]


# 在一行中画出多张图像并表示出对应标签
def show_fashion_mnist(images, labels):
    use_svg_display()
    _, figs = plt.subplots(1, len(images), figsize=(10, 5))
    for f, img, lbl in zip(figs, images, labels):
        f.imshow(img.reshape((28, 28)).asnumpy())
        f.set_title(lbl)
        f.axes.get_xaxis().set_visible(False)
        f.axes.get_yaxis().set_visible(False)
    # plt.savefig('images/part_of_predict_res.png')
    plt.show()


def load_data_fashion_mnist(batch_size):
    # 下载 FashionMNIST 数据集
    mnist_train = gdata.vision.FashionMNIST(train=True)  # 每一类衣服有6000张图像,10类共有60000张
    mnist_test = gdata.vision.FashionMNIST(train=False)  # 每一类衣服有1000张图像,10类共有10000张
    transformer = gdata.vision.transforms.ToTensor()  # ToTensor实例可将最后一维的通道移到最前一位
    if sys.platform.startswith('win'):
        num_workers = 0  # 0表示不用额外的进程来加速读取数据
    else:
        num_workers = 4
    train_iter = gdata.DataLoader(mnist_train.transform_first(transformer), batch_size, shuffle=True,
                                  num_workers=num_workers)
    test_iter = gdata.DataLoader(mnist_test.transform_first(transformer), batch_size, shuffle=False,
                                 num_workers=num_workers)
    return train_iter, test_iter


'''
读取数据
mxnet.gluon.data.vision.transforms 模块提供了预定义的视觉转换&数据增强方法
gdata.vision.transforms.Resize:Resize an image or a batch of image NDArray to the given size.
gdata.vision.transforms.ToTensor:Converts an image NDArray or batch of image NDArray to a tensor NDArray.
gdata.vision.transforms.Compose:Sequentially composes multiple transforms,顺序地组成多个变换
'''


def load_data_fashion_mnist_ch5(batch_size, resize=None,
                                root=os.path.join('~', '.mxnet', 'datasets', 'fashion-mnist')):
    root = os.path.expanduser(root)  # expanduser 可将参数中开头部分的 ~ 或 ~user 替换为当前用户的home目录并返回
    transformer = []
    if resize:
        transformer += [gdata.vision.transforms.Resize(resize)]  #
    transformer += [gdata.vision.transforms.ToTensor()]
    transformer = gdata.vision.transforms.Compose(transformer)
    # mnist_train = gdata.vision.FashionMNIST(root=root, train=True)
    # mnist_test = gdata.vision.FashionMNIST(root=root, train=False)
    mnist_train = gdata.vision.FashionMNIST(train=True)
    mnist_test = gdata.vision.FashionMNIST(train=False)
    num_workers = 0 if sys.platform.startswith('win32') else 4
    train_iter = gdata.DataLoader(mnist_train.transform_first(transformer), batch_size, shuffle=True,
                                  num_workers=num_workers)
    test_iter = gdata.DataLoader(mnist_test.transform_first(transformer), batch_size, shuffle=False,
                                 num_workers=num_workers)
    return train_iter, test_iter


'''
SGD:stochastic gradient descent,随机梯度下降
'''


def SGD(params, lr, batch_size):
    for param in params:
        param[:] = param - lr * param.grad / batch_size


'''
计算分类准确率
'''


def accuracy(yhat, y):
    return (yhat.argmax(axis=1) == y.astype('float32')).mean().asscalar()


def evaluate_accuracy_ch3(data_iter, net):
    acc_sum = 0.0
    n = 0
    for X, y in data_iter:
        acc_sum += (net(X).argmax(axis=1) == y.astype('float32')).sum().asscalar()
        n += y.size
    return acc_sum / n


def evaluate_accuracy_ch5(data_iter, net, ctx):
    acc_sum = nd.array([0], ctx=ctx)
    n = 0
    for X, y in data_iter:
        X = X.as_in_context(ctx)
        y = y.as_in_context(ctx).astype('float32')
        acc_sum += (net(X).argmax(axis=1) == y).sum().asscalar()
        n += y.size
    return acc_sum / n


'''
训练模型
'''


def train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size, params=None, lr=None, trainer=None):
    for epoch in range(num_epochs):
        train_loss = 0.0
        train_acc = 0.0
        n = 0
        for X, y in train_iter:
            with autograd.record():
                yhat = net(X)
                l = loss(yhat, y).sum()
            l.backward()
            if trainer is None:
                SGD(params, lr, batch_size)  # 将梯度做平均,这样学习率会对 batch_size 不那么敏感
            else:
                trainer.step(batch_size)  # 'softmax'回归的简单实现
            train_loss += l.asscalar()
            train_acc += (yhat.argmax(axis=1) == y.astype('float32')).sum().asscalar()
            n += y.size

        test_acc = evaluate_accuracy_ch3(test_iter, net)
        print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f'
              % (epoch + 1, train_loss / n, train_acc / n, test_acc))


def train_ch5(net, train_iter, test_iter, batch_size, trainer, ctx, num_epochs):
    print('training on', ctx)
    loss = gloss.SoftmaxCrossEntropyLoss()
    for epoch in range(num_epochs):
        train_loss = 0.0
        train_acc = 0.0
        n = 0
        start = time.time()
        for X, y in train_iter:
            X, y = X.as_in_context(ctx), y.as_in_context(ctx)
            with autograd.record():
                yhat = net(X)
                l = loss(yhat, y).sum()
            l.backward()
            trainer.step(batch_size)  # 'softmax'回归的简单实现
            train_loss += l.asscalar()
            train_acc += (yhat.argmax(axis=1) == y.astype('float32')).sum().asscalar()
            n += y.size

        test_acc = evaluate_accuracy_ch5(test_iter, net, ctx)
        print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f, time %.1f sec'
              % (epoch + 1, train_loss / n, train_acc / n, test_acc, time.time() - start))


'''
semilogy:轴半对数刻度曲线, y轴使用了对数尺度
'''


def semilogy(x_vals, y_vals, x_label, y_label, x2_vals=None, y2_vals=None, legend=None, figsize=(3.5, 2.5)):
    set_figsize(figsize)
    plt.xlabel(x_label)
    plt.ylabel(y_label)
    plt.semilogy(x_vals, y_vals)
    if x2_vals and y2_vals:
        plt.semilogy(x2_vals, y2_vals)
        plt.legend(legend)
    # plt.savefig('images/house_adaptive.png')
    plt.show()


'''
二维卷积运算
'''


def corr2d(X, K):  # K为核数组,X为输入数组
    h, w = K.shape
    Y = nd.zeros((X.shape[0] - h + 1, X.shape[1] - w + 1))  # 输出
    for i in range(Y.shape[0]):
        for j in range(Y.shape[1]):
            Y[i, j] = (X[i: i + h, j: j + w] * K).sum()
    return Y


'''
尝试使用 gpu 的代码
'''


def try_gpu():
    try:
        ctx = mx.gpu()
        _ = nd.zeros((1,), ctx=ctx)
    except mx.base.MXNetError:
        ctx = mx.cpu()
    return ctx

 

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;