【MindSpore】【深度学习Step by Step】(1-3)深度学习框架

  • Post author:
  • Post category:其他




深度学习框架



回顾

首先,我们来回顾一下前两节我们做了什么。

在第一节,我们建立了一个线性数据集,将其打包进行批量计算;通过加权求和的方式,建立了一个线性网络;使用平方误差作为损失函数;通过梯度下降的方式进行反向传播,使线性网络收敛。

在第二节,我们使用Mnist数据集,将其打包进行批量计算;使用了Softmax非线性网络;使用交叉熵作为损失函数;通过梯度下降的方式进行反向传播,使非线性网络收敛。

可以注意到,在两种方式中,我们的操作都有共同的成分,比如打开数据集、设置网络格式、选择误差函数、选择网络训练方法等。不可忽视的是,在前两节中,我们都采用手动求导的方法,进行梯度下降的操作,需要用户熟练掌握微积分。

但实际上,哪怕不是数学家或者信息学家,也能很好地使用深度学习,因为这些东西,深度学习框架都会自动帮我们处理,很多时候,我们需要做的,仅仅只是数据标注,以及超参数的调整而已,哪怕我们对模型的细节一无所知,也可以将其作为一个工具进行使用,这也是调参侠的由来。

下面,我们依照第二节,来了解一下MindSpore是如何为我们实现模型的训练的。



选择超参数

在这里,我们选择批处理量为256, 学习率为0.0001,训练轮次为10轮。

    batch_size, lr, num_epochs = 256, 0.0001, 10



加载数据集

在上一节中,我们使用

mindvision.classification.dataset

中的

Mnist

可以获取Mnist的数据集。同时,它也可以直接作为MindSpore框架的数据集,使用

    dataset_train = Mnist(path='/shareData/mindspore-dataset/Mnist', split="train",
                          batch_size=batch_size, repeat_num=1, shuffle=True,
                          download=False, resize=28).run()
    dataset_test = Mnist(path='/shareData/mindspore-dataset/Mnist', split="test",
                         batch_size=batch_size, repeat_num=1, shuffle=True,
                         download=False, resize=28).run()

即可将其作为MindSpore的标准数据集输入。

但如果我们要使用我们自己定义的方式加载数据,则需要进行一定的处理。

比如说我们要使用第二节自定义的

load_mnist

函数,首先要定义一个迭代器来输出数据与标签的值

def synthetic_data(features, labels):
    for i in range(len(labels)):
        yield features[i]/255, labels[i]

要自定义数据集,我们需要引用

mindspore.dataset

import mindspore.dataset as ds

下面的代码,第二行,我们使用了上述的迭代器;第三行,利用

mindspore.dataset.GeneratorDataset

来建立MindSpore可接受的数据集;第四行与第五行,我们对其进行格式转换;第七行,我们以一个batchsize的大小将其打包。

def data_iter(features, labels, batch_size):
    data_gen = synthetic_data(features, labels)
    data = ds.GeneratorDataset(tuple(data_gen), ['image', 'label'], shuffle=True)
    data = data.map(operations=[TypeCast(ms.dtype.float32)])
    data = data.map(operations=[TypeCast(ms.dtype.int32)],
                    input_columns='label')
    data = data.batch(batch_size)
    return data

使用下面的代码,即可将我们自建的数据集转换为MindSpore的格式。

    features_t, labels_t = load_mnist('/shareData/mindspore-dataset/Mnist/train')
    features_v, labels_v = load_mnist('/shareData/mindspore-dataset/Mnist/test', split='t10k')

    dataset_train = data_iter(features_t, labels_t, batch_size)
    dataset_valid = data_iter(features_v, labels_v, batch_size)



设置网络

在MindSpore中,我们的线性网络是

nn.Dense

(其实是全连接层),其计算方式为





y

=

a

c

t

i

v

a

t

i

o

n

(

W

X

T

+

B

)

y = activation(WX^T+B)






y




=








a


c


t


i


v


a


t


i


o


n


(


W



X










T











+








B


)





其中,activation可以是线性的,可以是非线性的,默认为线性的激活函数。

在官方的

文档

中,可以看到函数的说明:

mindspore.nn.Dense(in_channels, out_channels, weight_init='normal', bias_init='zeros', has_bias=True, activation=None)

其中,in_channels为输入的通道数,out_channels为输出的通道数,weight_init权重为初始化的方式(默认为高斯分布),bias_init为偏置的初始化方式(默认为0),has_bias为是否设置偏置,actitvation是上述提到的激活函数。

如果我们使用官方的数据集,可以使用下面的方式建立神经网络。

    net = nn.SequentialCell(
        nn.Flatten(),
        nn.Dense(28*28, 10),
    )

使用我们自定义的数据集,只需要下面的方式即可。

    net = nn.Dense(28*28, 10)



设置损失函数

设置Softmax输出层的交叉熵损失函数非常简单,只需要一句话:

    loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')



设置优化器

现在,我们不需要手动求导来获得梯度了。我们可以直接使用SGD优化器,可以自动进行优化。

    opti = nn.SGD(net.trainable_params(), learning_rate=lr)



回调函数

回调函数是在训练过程中会被调用的函数,在之后的章节中会详细说明(下面的函数在util.callback文件中)。

def get_accuracy(network, datasets):
    metric = nn.Accuracy('classification')
    for x, y in datasets:
        y_hat = network(x)
        metric.update(y_hat, y)
    return metric.eval()
def get_loss(network, loss_f, dataset):
    loss = 0
    for x, y in dataset:
        y_hat = network(x)
        loss += loss_f(y_hat, y)
    return loss
class AccuracyMonitor(ms.Callback):
    def __init__(self, valid_data):
        self.valid_data = valid_data

    def on_train_epoch_end(self, run_context):
        """Called after each epoch finished."""

        callback_params = run_context.original_args()

        cur_epoch_num = callback_params.cur_epoch_num
        epoch_num = callback_params.epoch_num

        network = callback_params.network

        train_data = callback_params.train_dataset

        train_accu = get_accuracy(network, train_data)
        valid_accu = get_accuracy(network, self.valid_data)

        loss = get_loss(network, callback_params.loss_fn, train_data)
        loss /= callback_params.batch_num

        print(f'epoch:[{cur_epoch_num}/{epoch_num}] Loss:{loss} Train Accuracy:{train_accu} Valid Accuracy:{valid_accu}')



训练模型

在MindSpore提供模型训练的高阶API,使用以下的短短两行代码即可进行训练。

    model = ms.Model(net, loss_fn=loss, optimizer=opti, metrics={'acc'})

    model.train(num_epochs, dataset_train, callbacks=[AccuracyMonitor(dataset_valid)])



输出结果

epoch:[1/10] Loss:2.2774138 Train Accuracy:0.14748333333333333 Valid Accuracy:0.155
epoch:[2/10] Loss:2.252627 Train Accuracy:0.19975 Valid Accuracy:0.2083
epoch:[3/10] Loss:2.2284462 Train Accuracy:0.2749666666666667 Valid Accuracy:0.2841
epoch:[4/10] Loss:2.2046874 Train Accuracy:0.3722666666666667 Valid Accuracy:0.3815
epoch:[5/10] Loss:2.1814284 Train Accuracy:0.46326666666666666 Valid Accuracy:0.4711
epoch:[6/10] Loss:2.1586423 Train Accuracy:0.5326166666666666 Valid Accuracy:0.5395
epoch:[7/10] Loss:2.136246 Train Accuracy:0.58175 Valid Accuracy:0.588
epoch:[8/10] Loss:2.11424 Train Accuracy:0.6151666666666666 Valid Accuracy:0.6216
epoch:[9/10] Loss:2.0927134 Train Accuracy:0.6402666666666667 Valid Accuracy:0.6477
epoch:[10/10] Loss:2.071551 Train Accuracy:0.6594166666666667 Valid Accuracy:0.669



版权声明:本文为muronglengjing原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。