作为“helloworld!”在图像识别和机器视觉领域,MNIST(“修改后的美国国家标准与技术研究所”)数据集起着举足轻重的作用。基本上每一本与人工智能和机器学习相关的书都是从它开始的。下面我们将使用TensorFlow构建一个浅层神经网络来运行“helloworld!”模型。以下内容和模块的计算均在巨池云平台上进行。本教程分为五个步骤:Step1:数据预处理,包括提取数据标签、查看图像数据、数据可视化、检查数据是否平衡等Step2:数据加载、打乱数据集Step3:构建一个model,简单介绍网络卷积模型和激活函数,定义训练函数和学习率Step4:模型训练,查看训练过程和结果,用图查看模型准确率和学习率变化Step5:尝试改进准确性和继续探索在构建和优化之前,我们需要加载以下相应的模块:第一步:数据预处理1.1查看数据标签在构建任何模型之前,您应该首先检查数据。比如数据集的大小,训练集和测试集的数据个数,label中数据个数的分布等。下面是训练集和测试集的数据查看代码:train=pd.read_csv('mnist/mnist_train.csv')#读取traintest=pd.read_csv('mnist/mnist_test.csv')#下面读取train是训练集和测试集个数的结果:train.shape(6000,785)test.shape(10000,785)我们可以看到train训练集有6000条数据,test测试集有10000条数据,每行两个测试集有785个数据。接下来我们看一下数据集的预览:第一列是标签列,其余784列是像素数据。784列数据构成了一个28*28像素的图像。1.2提取数据标签接下来,我们提取和处理数据标签。先看标签数据的提取代码:train_labels=np.array(train.pop('label'))test_labels=np.array(test.pop('label'))查看标签类型,可以看到labelrepresentation包括0到9的数字,没有其他错误的数据。由于计算需要,我们需要将一维图像数据转换为二维图像数据。将图像数据转换为长28、宽28、通道1的格式,方便卷积计算。Step2:数据可视化2.1随机生成的数据匹配现在随机选择一些我们转换后的图像数据,使用matplot检查标签和图像是否可以匹配。盒子里面是随机生成的非常规文字,图片上方中间是对应的数字。2.2检查数据是否平衡分类器的设计是基于类分布大致平衡的假设。通常假设用于训练的数据是平衡的,即每一类包含的样本数大致相等。接下来我们看一下标签的分布情况,看看每个标签类型的数据量是否分布均匀。在MINST数据集中,我们的数据呈均匀分布。sns.distplot(train_labels,kde=False,bins=10)2.3数据加载在建立模型之前,我们需要定义一些常量:#图像宽度width=28#图像高度height=28#batchsizebatch_size=100#训练次数imagestrain_images_num=train.shape[0]接下来,我们为模型构建数据集。TensorFlow提供了Dataset类来方便加载训练数据,使用tf.data.Dataset。其中,训练集中的数据,我们是随机打乱的。train=tf.cast(train,tf.float32)test=tf.cast(test,tf.float32)train_ds=tf.data.Dataset.from_tensor_slices((train,train_labels)).shuffle(train_images_num).batch(batch_size)test_ds=tf.data.Dataset.from_tensor_slices((test,test_labels)).batch(batch_size)第三步:模型构建3.1模型构建的网络层次结构数字识别是一个入门项目,我们的模型会比较简单。目前的构建模型采用如下网络层级结构:第一层二维卷积层Flattenlayer:该层的作用是将第一层的卷积压扁压缩成一维,常用于from卷积层对全连接过度连接,当然Flatten不影响batch的大小Denselayer:全连接神经网络层Denselayer:全连接神经网络层每层对应的激活函数如下:第一层使用ReLU函数Flattenlayer(none)DenselayerReLU函数Dense层使用softmax损失函数输出3.2激活函数的解释ReLU函数ReLU函数的全称是RectifiedLinearUnit(ReLU),也称为人工神经网络中常用的校正线性单元。激活函数(activationfunction),通常是指以斜坡函数及其变体为代表的非线性函数。ReLU的函数表达式为:用向量形式表示:函数曲线的形状为:从函数的表达式可以看出函数抑制了小于0的输入,这个激活函数有以下特点:收敛速度快,在[0,x]区间不会饱和,即可以抵抗梯度消失问题,推导简单,即计算效率很高。softmax函数softmax用在多分类过程中,它将多个神经元的输出映射到(0,1)区间,可以理解为一个概率,从而进行多分类。让我们看看它的数学表达式。假设我们有一个数组,?V,??Vi代表?V中的第i个元素,那么这个元素的softmax值为:在我们的数字识别模型中,我们将最终的结果输出成一个10个元素的数组,数组从下标0到9开始,分别代表对应的标签。然后对这个输出进行softmax计算,取出softmax值最大的元素对应的label作为我们的分类结果。类MNIST(模型):def__init__(self):super(MNIST,self).__init__()self.conv1=Conv2D(width,3,activation='relu')self.flatten=Flatten()self.d1=Dense(128,activation='relu')self.d2=Dense(10,activation='softmax')defcall(self,x):x=self.conv1(x)x=self.flatten(x)x=self.d1(x)returnself.d2(x)model=MNIST()model.build(input_shape=train.shape3.3查看模型的构建本文使用汇总界面查看模型的情况,可以看到我们每一层的网络类型,输出,参数个数,可训练参数和所有参数的统计信息都在最下面。我们选择交叉熵函数作为我们的损失函数,基本公式如下:批处理公式:使用随机梯度下降算法作为我们的优化器:loss_object=tf.keras.losses.SparseCategoricalCrossentropy()optimizer=tf.keras.optimizers。SGD()train_loss=tf.keras.metrics.Mean(name='train_loss')train_accuracy=tf.keras.metrics.SparseCategoricalAccuracy(name='train_accuracy')test_loss=tf.keras.metrics.Mean(name='test_loss')test_accuracy=tf.keras.metrics.SparseCategoricalAccuracy(name='test_accuracy')定义train_step函数:@tf.functiondeftrain_step(images,labels):withtf.GradientTape()astape:predictions=model(images)loss=loss_object(labels,predictions)gradients=tape.gradient(loss,model.trainable_variables)optimizer.apply_gradients(zip(gradients,model.trainable_variables))train_loss(loss)train_accuracy(labels,predictions)定义test_step函数:@tf.function(images_step标签):预测=模型(图像)t_loss=loss_object(标签,预测)test_loss(t_loss)test_accuracy(labels,predictions)一般情况下,学习率(learningrate)不适合设为常量。在连续训练迭代的情况下,恒定的学习率会导致模型收敛性差。在不断迭代的过程中,损失函数(loss)越来越小,所以我们希望学习率也越来越小,这样模型才能收敛到更好的局部最优。这里我们简单的让学习率每个epoch下降一定量。deflr_fn(epoch,lr):ifepoch==0:return0.001returnlr*0.9设置一个更大的epoch,我们在模型训练时实现了早停策略。当训练精度小于上一个epoch的精度时,我们认为模型过度拟合。我们将停止训练这也是一种防止过拟合的策略。Step4:模型训练我们记录了训练过程中每个epoch的训练集和测试集的准确率统计和学习率,以便在训练完成后检查训练过程的效果。我们可以看到的训练结果:然后我们把训练中记录的训练集和测试集的准确率结果放到图表中,可以查看我们的训练情况:绿色是测试集曲线,蓝色是训练集曲线。plt.plot(epoch_range,train_accuracy_total,'-b',label="training")plt.plot(epoch_range,test_accuracy_total,'-g',label="test")plt.legend()plt.xlabel('epoch')plt.ylabel('accuracy')从图表中可以看出,经过连续的epoch迭代后,模型的accuracy在前几个epoch后迅速增加(这意味着收敛速度非常快)。在接下来的几个epoch中,模型的准确率曲线趋于平坦,收敛速度变慢。查看学习率的递减情况:plt.plot(epoch_range,lr_total,'-b',label="training")plt.legend()plt.xlabel('epoch')plt.ylabel('learningrate')五Step:Explorationandoptimization后续读者可以从以下几个方面来尝试提高模型的准确率。更深的网络层级,可以更换模型,比如使用VGG16、ResNet等更深的网络,或者在现有网络上增加更多的卷积层来尝试更多的训练数据,数据量的增长可以大大提高准确率和泛化能力的模型使用其他优化器,例如:adam调整学习率时刻Chiyun现在已经推出了“MachineImageRecognition”图像;选择“ImageRecognitiondemo”图片,机器启动后,在JupyterLab目录digit-recognizer文件夹中选择它,JuchiCloud已经在里面集成了数据集和脚本,执行里面的ipynb文件运行上面的识别脚本。
