# coding: utf-8 import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data import os import argparse import moxing as mox os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' workroot = '/home/work/user-job-dir' #初始化过滤器 def weight_variable(shape): return tf.Variable(tf.truncated_normal(shape, stddev=0.1)) #初始化偏置,初始化时,所有值是0.1 def bias_variable(shape): return tf.Variable(tf.constant(0.1, shape=shape)) #卷积运算,strides表示每一维度滑动的步长,一般strides[0]=strides[3]=1 #第四个参数可选"Same"或"VALID",“Same”表示边距使用全0填充 def conv2d(x, W): return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding="SAME") #池化运算 def max_pool_2x2(x): return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME") def parse_args(): parser = argparse.ArgumentParser(description='MindSpore Lenet Example') # define 2 parameters for running on modelArts # data_url,train_url是固定用于在modelarts上训练的参数,表示数据集的路径和输出模型的路径 parser.add_argument('--data_url', help='path to training/inference dataset folder', default= workroot + '/data/') parser.add_argument('--train_url', help='model folder to save/load', default= workroot + '/model/') parser.add_argument( '--device_target', type=str, default="Ascend", choices=['Ascend', 'CPU'], help='device where the code will be implemented (default: CPU),若要在启智平台上使用NPU,需要在启智平台训练界面上加上运行参数device_target=Ascend') #modelarts已经默认使用data_url和train_url parser.add_argument('--epoch_size', type=int, default=5, help='Training epochs.') args = parser.parse_args() return args if __name__ == "__main__": args = parse_args() print('args:') print(args) mnist = input_data.read_data_sets('mnist_data', one_hot=True) #创建x占位符,用于临时存放MNIST图片的数据, # [None, 784]中的None表示不限长度,而784则是一张图片的大小(28×28=784) x = tf.placeholder(tf.float32, [None, 784], name='input') #y_存的是实际图像的标签,即对应于每张输入图片实际的值 y_ = tf.placeholder(tf.float32, [None, 10]) #将图片从784维向量重新还原为28×28的矩阵图片, # 原因参考卷积神经网络模型图,最后一个参数代表深度, # 因为MNIST是黑白图片,所以深度为1, # 第一个参数为-1,表示一维的长度不限定,这样就可以灵活设置每个batch的训练的个数了 x_image = tf.reshape(x, [-1, 28, 28, 1]) #第一层卷积 #将过滤器设置成5×5×1的矩阵, #其中5×5表示过滤器大小,1表示深度,因为MNIST是黑白图片只有一层。所以深度为1 #32表示我们要创建32个大小5×5×1的过滤器,经过卷积后算出32个特征图(每个过滤器得到一个特征图),即输出深度为64 W_conv1 = weight_variable([5, 5, 1, 32]) #有多少个特征图就有多少个偏置 b_conv1 = bias_variable([32]) #使用conv2d函数进行卷积计算,然后再用ReLU作为激活函数 h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1) #卷积以后再经过池化操作 h_pool1 = max_pool_2x2(h_conv1) #第二层卷积 #因为经过第一层卷积运算后,输出的深度为32,所以过滤器深度和下一层输出深度也做出改变 W_conv2 = weight_variable([5, 5, 32, 64]) b_conv2 = bias_variable([64]) h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2) h_pool2 = max_pool_2x2(h_conv2) #全连接层 #经过两层卷积后,图片的大小为7×7(第一层池化后输出为(28/2)×(28/2), #第二层池化后输出为(14/2)×(14/2)),深度为64, #我们在这里加入一个有1024个神经元的全连接层,所以权重W的尺寸为[7 * 7 * 64, 1024] W_fc1 = weight_variable([7 * 7 * 64, 1024]) #偏置的个数和权重的个数一致 b_fc1 = bias_variable([1024]) #这里将第二层池化后的张量(长:7 宽:7 深度:64) 变成向量(跟上一节的Softmax模型的输入一样了) h_pool2_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 64]) #使用ReLU激活函数 h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1) #dropout #为了减少过拟合,我们在输出层之前加入dropout keep_prob = tf.placeholder(tf.float32, name='keep_prob') h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob) #输出层 #全连接层输入的大小为1024,而我们要得到的结果的大小是10(0~9), # 所以这里权重W的尺寸为[1024, 10] W_fc2 = weight_variable([1024, 10]) b_fc2 = bias_variable([10]) #最后都要经过Softmax函数将输出转化为概率问题 y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2, name='output') #损失函数和损失优化 cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y_conv))) train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy) #测试准确率,跟Softmax回归模型的一样 correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) train_dir = workroot + '/model/' #模型存放路径 if not os.path.exists(train_dir): os.mkdir(train_dir) obs_train_url = args.train_url #开始训练 with tf.Session() as sess: #初始化所有变量 sess.run(tf.global_variables_initializer()) #训练两万次 for i in range(2000): #每次获取50张图片数据和对应的标签 batch = mnist.train.next_batch(50) #每训练100次,我们打印一次训练的准确率 if i % 100 == 0: train_accuracy =sess.run(accuracy, feed_dict={x:batch[0], y_:batch[1], keep_prob:1.0}) print("step %d, training accuracy %g" % (i, train_accuracy)) #这里是真的训练,将数据传入 sess.run(train_step, feed_dict={x:batch[0], y_:batch[1], keep_prob:0.5}) # 用SavedModel的方式保存 tf.compat.v1.saved_model.simple_save(sess, train_dir +"saved_model", inputs={"input": x, 'keep_prob':keep_prob}, outputs={"output": y_conv}) try: mox.file.copy_parallel(train_dir, obs_train_url) print("Successfully Upload {} to {}".format(train_dir,obs_train_url)) except Exception as e: print('moxing upload {} to {} failed: '.format(train_dir,obs_train_url) + str(e))