使用MindSpore实现一个简单的线性函数拟合
1、环境准备设置MindSpore运行配置from mindspore import contextcontext.set_context(mode=context.GRAPH_MODE, device_target="CPU")本教程代码依赖matplotlib第三方支持包,可使用命令pipinstallmatplotlib安装。
2、生成数据集定义数据集生成函数get_data用于生成训练数据集和测试数据集。由于拟合的是线性数据,假定要拟合的目标函数为:f(x)=2x+3f(x)=2x+3,那么我们需要的训练数据集应随机分布于函数周边,这里采用了f(x)=2x+3+noisef(x)=2x+3+noise的方式生成,其中noise为遵循标准正态分布规律的随机数值。import numpy as npdef get_data(num, w=2.0, b=3.0): for _ in range(num): x = np.random.uniform(-10.0, 10.0) noise = np.random.normal(0, 1) y = x * w + b + noise yield np.array([x]).astype(np.float32), np.array([y]).astype(np.float32)使用get_data生成50组测试数据,可视化展示。import matplotlib.pyplot as plteval_data = list(get_data(50))x_target_label = np.array([-10, 10, 0.1])y_target_label = x_target_label * 2 + 3x_eval_label,y_eval_label = zip(*eval_data)plt.scatter(x_eval_label, y_eval_label, color="red", s=5)plt.plot(x_target_label, y_target_label, color="green")plt.title("Eval data")plt.show()
3、定义数据增强函数先使用MindSpore的数据转换函数GeneratorDataset转换成适应MindSpore训练的数据类型,然后再使用batch、repeat对数据进行增强操作,操作解释如下:ds.GeneratorDataset:将生成的数据转换为MindSpore的数据集,并且将生成的数据的x,y值存入到data和label的数组中。batch:将batch_size个数据组合成一个batch。repeat:将数据集数量倍增。from mindspore import dataset as dsdef create_dataset(num_data, batch_size=16, repeat_size=1): input_data = ds.GeneratorDataset(list(get_data(num_data)), column_names=['data', 'label']) input_data = input_data.batch(batch_size) input_data = input_data.repeat(repeat_size) return input_data使用数据集增强函数生成训练数据,并查看训练数据的格式。data_number = 1600batch_number = 16repeat_number = 1ds_train = create_dataset(data_number, batch_size=batch_number, repeat_size=repeat_number)print("The dataset size of ds_train:", ds_train.get_dataset_size())dict_datasets = next(ds_train.create_dict_iterator())print(dict_datasets.keys())print("The x label value shape:", dict_datasets["data"].shape)print("The y label value shape:", dict_datasets["label"].shape)
4、定义训练网络在MindSpore中使用nn.Dense生成单个数据输入,单个数据输出的线性函数模型:f(x)=wx+b(1)并使用Normal算子随机初始化权重w和b。from mindspore.common.initializer import Normalfrom mindspore import nnclass LinearNet(nn.Cell): def __init__(self): super(LinearNet, self).__init__() self.fc = nn.Dense(1, 1, Normal(0.02), Normal(0.02)) def construct(self, x): x = self.fc(x) return x
5、定义前向传播网络与反向传播网络并关联接下来需要定义模型的损失函数,这里采用均方误差(MSE,Mean Squared Error)的方法用于判断拟合的效果如何,即均方误差值越小,拟合的效果越好,其损失函数公式为:J(w)=12m∑i=1m(h(xi)−y(i))假设训练数据第ii个数据为(xi,y(i)),公式2中的参数解释如下:J(w)为损失值。m为样本数据的数量,本例中m的值为batch_number。h(xi)为第ii个数据的xi值代入模型网络(公式1)后的预测值。y(i)为第i个数据中的y(i)值(label值)。定义前向传播网络前向传播网络包含两个部分,其中:将参数带入到模型网络中得出预测值。使用预测值和训练数据计算出loss值。在MindSpore中使用如下方式实现。net = LinearNet()net_loss = nn.loss.MSELoss()
6、关联前向和反向传播网络定义完成前向传播和反向传播后,在MindSpore中需要调用Model函数,将前面定义的网络,损失函数,优化器函数关联起来,使之变成完整的计算网络。from mindspore import Modelmodel = Model(net, net_loss, opt)
7、执行训练完成以上过程后,可以使用训练数ds_train对模型训练,这里调用model.train进行,其中参数解释:epoch:训练迭代的整个数据集的次数。ds_train:训练数据集。callbacks:训练过程中需要调用的回调函数。dataset_sink_mode:数据集下沉模式,支持Ascend、GPU计算平台,本例为CPU计算平台设置为False。from mindspore.train.callback import LossMonitorepoch = 1imageshow_cb = ImageShowCallback(net, eval_data)model.train(epoch, ds_train, callbacks=[imageshow_cb], dataset_sink_mode=False)plot_model_and_datasets(net, eval_data)for param in net.trainable_params(): print(param, param.asnumpy())
8、本次体验我们了解了线性拟合的算法原理,并在MindSpore框架下实现了相应的算法定义,了解了线性拟合这类的线性回归模型在MindSpore中的训练过程,并最终拟合出了一条接近目标函数的模型函数。另外有兴趣的可以调整数据集的生成区间从(-10,10)扩展到(-100,100),看看权重值是否更接近目标函数;调整学习率大小,看看拟合的效率是否有变化;当然也可以探索如何使用MindSpore拟合f(x)=ax2+bx+cf(x)=ax2+bx+c这类的二次函数或者更高次的函数。