当前位置:首页 >> 开发者生态 >> 【TensorFlow-windows】学习笔记三——实战准备,lg gd330

【TensorFlow-windows】学习笔记三——实战准备,lg gd330

cpugpu芯片开发光刻机 开发者生态 1
文件名:【TensorFlow-windows】学习笔记三——实战准备,lg gd330 【TensorFlow-windows】学习笔记三——实战准备 前言

因为学习TensorFlow的内容较多,如果只看API会很无聊,可以结合实例去学习。但是在构建基本的模型之前,需要学一些准备知识:数据读取、预处理、优化器、损失函数

国际惯例,参考网址:

TensorFlow中文社区

TensorFlow官方文档

如何选择优化器 optimizer

TensorFlow-Examples

TensorFlow中的Neural Network

TensorFlow中的Train

深入浅出Tensorflow(三):训练神经网络模型的常用方法

理解tf.train.slice_input_producer()和tf.train.batch()

此外,为了模拟现实数据集,这里将mnist手写数字数据集转换成图片格式存储,放一下网盘链接:链接:https://pan.baidu.com/s/1ugEy85182vjcXQ8VoMJAbg 密码:1o83

处理数据集 从文本文件读取图像数据

按照caffe的读取习惯,把图片的路径和标签全部用txt文本文件存储起来,即路径\图片名 标签的格式:

./mnist/train/5/5_1.png 5./mnist/train/0/0_2.png 0./mnist/train/4/4_3.png 4./mnist/train/1/1_4.png 1

然后参考TensorFlow-Examples中的build_an_image_dataset 方法按照文本文件中存储的路径和标签去按行读取

imagepaths, labels = list(), list()data = open(dataset_path, 'r').read().splitlines()for d in data:imagepaths.append(d.split(' ')[0])labels.append(int(d.split(' ')[1])) 在TF中打乱数据以及分批

因为我们要用tensorflow处理数据,所以必须将这些文本转换成tensorflow能处理的形式

# 转换为张量imagepaths = tf.convert_to_tensor(imagepaths, dtype=tf.string)labels = tf.convert_to_tensor(labels, dtype=tf.int32) 打乱数据 # 建立TF队列,打乱数据image, label = tf.train.slice_input_producer([imagepaths, labels],shuffle=True)

这里看一下这个slice_input_producer函数:

tf.train.slice_input_producer(tensor_list,num_epochs=None,shuffle=True,seed=None,capacity=32,shared_name=None,name=None) 作用:为tensor_list中的每个Tensor建立切片部分参数: tensor_list:Tensor形式的列表,第一个维度必须相同 num_epochs:每个切片创建多少次 shuffle:打乱顺序

所以在打乱顺序的时候将此函数的shuffle参数设置成True即可

图片读取和处理

打乱数据路径以后,就可以读取了,tensorflow也提供了图像处理相关函数,这里列部分有用的:

调整图像亮度:

tf.image.adjust_brightness(image,delta)

调整图像对比度:

tf.image.adjust_contrast(images,contrast_factor)

伽马校正:

tf.image.adjust_gamma(image,gamma=1,gain=1)

从中间向边缘裁剪图像:

tf.image.central_crop(image,central_fraction)

裁剪图片,分别是左上角纵坐标、横坐标,裁剪的高度、宽度:

tf.image.crop_to_bounding_box(image,offset_height,offset_width,target_height,target_width)

图像解码:将对应图像解码为uint8张量(还有对应编码的encode函数):

tf.image.decode_bmptf.image.decode_giftf.image.decode_imagetf.image.decode_jpegtf.image.decode_png

图像翻转:

tf.image.flip_left_right左右翻转tf.image.flip_up_down上下翻转tf.image.rot90翻转90度,可自定义次数tf.image.transpose_image图像转置

图像转换:

tf.image.grayscale_to_rgb:灰度图转换为RGBtf.image.hsv_to_rgb:HSV图转换为RGBtf.image.rgb_to_grayscale:RGB转灰度图tf.image.rgb_to_hsv:RGB转HSVtf.image.rgb_to_yiq:RGB转YIQtf.image.rgb_to_yuv:RGB转YUVtf.image.yiq_to_rgb:YIQ转RGBtf.image.yuv_to_rgb:YUV转RGB

图像填充:

tf.image.pad_to_bounding_box(image,offset_height,offset_width,target_height,target_width)

在图像上面填充offset_height高度的0,在图像左边填充offset_width宽度的0,再按照最终目标宽度和高度在下边和右边填充图像。

图像归一化:tf.image.per_image_standardization(image)

图像大小调整

tf.image.resize_images(images,size,method=ResizeMethod.BILINEAR,align_corners=False)

其中插值方法有:

AREABICUBICBILINEARNEAREST_NEIGHBOR

所以在图像预处理过程中,先按照路径读取图像以及解码,然后调整图像大小,归一化:

# 读取数据image = tf.read_file(image)image = tf.image.decode_jpeg(image, channels=CHANNELS)# 将图像resize成规定大小image = tf.image.resize_images(image, [IMG_HEIGHT, IMG_WIDTH])# 手动归一化image = image * 1.0/127.5 - 1.0 创建批量数据

就一个函数:

tf.train.batch(tensors,batch_size,num_threads=1,capacity=32,enqueue_many=False,shapes=None,dynamic_pad=False,allow_smaller_final_batch=False,shared_name=None,name=None) 作用:利用队列的方法存储批数据部分参数: tensors:张量列表或者字典 batch_size:批大小 num_thread:并行入队,采用线程数 capacity:整数,队列里面最多有多少个元素

在制作数据集中,直接这样:

# 创建batchX, Y = tf.train.batch([image, label], batch_size=batch_size,capacity=batch_size * 8,num_threads=4)

具体可以参考这篇博客的描述:TensorFlow 组合训练数据(batching)、TensorFlow 笔记(九):数据读取

TF中神经网络相关函数

这里需要注意的是tf.layers和tf.nn中均有相关层的实现,它们之间的区别我也不太清楚,但是从网上的观点来看,大部分人认为前者是以后者作为后端的,具体分析可看:

tf.nn.conv2d vs tf.layers.conv2d

tensorflow学习:tf.nn.conv2d 和 tf.layers.conv2d

Neural Network

层相关

目前构建神经网络还是使用前者的吧:

average_pooling1d(...): 一维输入平均池化average_pooling2d(...): 二维输入平均池化(比如图像)average_pooling3d(...): 三维输入平均池化(比如立体)batch_normalization(...): 批归一化conv1d(...): 一维卷积conv2d(...): 二维卷积conv2d_transpose(...): 2D反卷积conv3d(...): 三维卷积conv3d_transpose(...): 三维转置卷积dense(...): 全连接dropout(...): 随机丢失神经元flatten(...): 保存第一个维度去展平数据max_pooling1d(...): 一维输入最大池化max_pooling2d(...): 二维输入最大池化max_pooling3d(...): 三维输入最大池化separable_conv1d(...): 按照深度独立方法一维卷积separable_conv2d(...): 按照深度独立方法二维卷积 激活函数和损失相关

而tf.nn也不是完全没用,它存储了激活函数以及部分损失函数:

sigmoid(...): sigmoid激活函数tanh(...): tanh激活函数softplus(...): 激活函数 log(exp(features) + 1).relu(...): ReLU激活函数leaky_relu(...): Leaky ReLU 激活函数max(features,leak*features)elu(...): ELU激活函数:features if features>0 else alpha*(e^features-1)selu(...): scaled exponential linear: scale * alpha * (exp(features) - 1)crelu(...): 关联ReLU激活函数relu6(...): Rectified Linear 6: min(max(features, 0), 6).softmax(...): softmax 激活函数(一般用于最后一层)softsign(...): 激活函数 features / (abs(features) + 1).dropout(...):神经元抑制ctc_loss(...): CTC (Connectionist Temporal Classification)损失nce_loss(...):计算noise-contrastive estimation训练损失l2_loss(...): L2 损失.log_poisson_loss(...): log Poisson损失.weighted_cross_entropy_with_logits(...): 加权交叉熵损失(默认已将features用softmax激活)sparse_softmax_cross_entropy_with_logits(...): 计算logits 和 labels的稀疏交叉熵损失softmax_cross_entropy_with_logits(...): 计算logits 和 labels的交叉熵损失(默认已将features用softmax激活)softmax_cross_entropy_with_logits_v2(...): 计算logits 和 labels的交叉熵损失(默认已将features用softmax激活)sigmoid_cross_entropy_with_logits(...): 经sigmoid 函数激活之后的交叉熵(默认已将features用softmax激活)moments(...): 计算输入数据的均值和方差.normalize_moments(...): 基于sufficient statistics计算输入数据的均值和方差top_k(...): 返回最后一个维度的k个最大值和索引in_top_k(...):查询目标值是否在k个预测值中xw_plus_b(...): 计算 matmul(x, weights) + biases.relu_layer(...): 计算 Relu(x * weight + biases).

这里几个地方需要注意:

l2_loss损失函数:没有开方,并且只取一半output=12x2output=12∑x2xxx__with_logits:类似于这样的都是已经将输出用softmax激活,然后计算误差,相当于做了两步工作:softmax激活输出、计算其log值与原始标签的乘积的和,具体介绍戳这里 正则项

两种正则化方法,三种函数:

一范式正则化:

tf.contrib.layers.l1_regularizer(scale,scope=None)

二范式正则化:

tf.contrib.layers.l2_regularizer(scale,scope=None)

两种范式一起用

tf.contrib.layers.l1_l2_regularizer(scale_l1=1.0,scale_l2=1.0,scope=None)

最后要将正则化应用到权重中:

tf.contrib.layers.apply_regularization(regularizer,weights_list=None) TF中的训练方法

包含优化器、梯度计算、梯度裁剪、学习率及其衰减,参考这里

优化器 OptimizerGradientDescentOptimizerAdadeltaOptimizerAdagradOptimizerAdagradDAOptimizerMomentumOptimizerAdamOptimizerFtrlOptimizerProximalGradientDescentOptimizerProximalAdagradOptimizerRMSPropOptimizer

各种梯度优化器,注意他们是属于类,对应有很多函数可调用,比如minimize

梯度计算 gradientsAggregationMethodstop_gradienthessians 梯度裁剪 clip_by_valueclip_by_normclip_by_average_normclip_by_global_normglobal_norm 学习率及其衰减 exponential_decayinverse_time_decaynatural_exp_decaypiecewise_constantpolynomial_decaycosine_decaylinear_cosine_decaynoisy_linear_cosine_decay

一般不用搞那么复杂,随便用两个就行:

指数形式的衰减方法

tf.train.exponential_decay(learning_rate,#初始学习率global_step,#非负,衰减指数decay_steps,#正数,衰减周期decay_rate,#衰减率staircase=False,#如果是True,就是离散形式的衰减name=None)'''decayed_learning_rate = learning_rate *decay_rate ^ (global_step / decay_steps)staircase是True的时候(global_step / decay_steps)转换为整数'''

多项式衰减:

tf.train.polynomial_decay(learning_rate,global_step,decay_steps,end_learning_rate=0.0001,power=1.0,cycle=False,name=None)

其中的cycle参数是决定lr是否在下降后重新上升的过程。cycle参数的初衷是为了防止网络后期lr十分小导致一直在某个局部最小值中振荡,突然调大lr可以跳出注定不会继续增长的区域探索其他区域。

没cycle时的计算方法:

global_step = min(global_step, decay_steps)decayed_learning_rate = (learning_rate - end_learning_rate) *(1 - global_step / decay_steps) ^ (power) +end_learning_rate

有cycle时的计算方法:

decay_steps = decay_steps * ceil(global_step / decay_steps)decayed_learning_rate = (learning_rate - end_learning_rate) *(1 - global_step / decay_steps) ^ (power) +end_learning_rate 一般使用流程

一般是先定义学习率,然后使用优化器最小化损失

比如使用指数衰减:

...global_step = tf.Variable(0, trainable=False)starter_learning_rate = 0.1learning_rate = tf.train.exponential_decay(starter_learning_rate, global_step,100000, 0.96, staircase=True)# Passing global_step to minimize() will increment it at each step.learning_step = (tf.train.GradientDescentOptimizer(learning_rate).minimize(...my loss..., global_step=global_step))

比如使用多项式衰减

...global_step = tf.Variable(0, trainable=False)starter_learning_rate = 0.1end_learning_rate = 0.01decay_steps = 10000learning_rate = tf.train.polynomial_decay(starter_learning_rate, global_step,decay_steps, end_learning_rate,power=0.5)# Passing global_step to minimize() will increment it at each step.learning_step = (tf.train.GradientDescentOptimizer(learning_rate).minimize(...my loss..., global_step=global_step))

这个global_step随着训练自增,具体可以看这里

用这段代码可以看出来:

import tensorflow as tf; import numpy as np; import matplotlib.pyplot as plt; x = tf.placeholder(tf.float32, shape=[None, 1], name='x')y = tf.placeholder(tf.float32, shape=[None, 1], name='y')w = tf.Variable(tf.constant(0.0))global_steps = tf.Variable(0, trainable=False)learning_rate = tf.train.exponential_decay(0.1, global_steps, 10, 2, staircase=False)loss = tf.pow(w*x-y, 2)train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_steps)with tf.Session() as sess:sess.run(tf.initialize_all_variables())for i in range(10):sess.run(train_step, feed_dict={x:np.linspace(1,2,10).reshape([10,1]),y:np.linspace(1,2,10).reshape([10,1])})print (sess.run(global_steps))

注意,经常无需人工计算梯度然后apply到相关参数列表上,因为minimize已经包含这两步骤了。

简单例子

按照这个例子很容易利用CNN实现一个手写数字识别网络 先引入相关包以及定义数据相关信息

import tensorflow as tfimport osDATASET_PATH = './mnist/train_labels.txt' # the dataset file or root folder path.N_CLASSES = 10 # 类别数IMG_HEIGHT = 28 # 高IMG_WIDTH = 28 # 宽CHANNELS = 1 # 通道数

然后按照标签中定义的图片路径和标签,制作数据集:

def read_images(dataset_path, batch_size):imagepaths, labels = list(), list()data = open(dataset_path, 'r').read().splitlines()for d in data:imagepaths.append(d.split(' ')[0])labels.append(int(d.split(' ')[1]))# 转换为张量imagepaths = tf.convert_to_tensor(imagepaths, dtype=tf.string)labels = tf.convert_to_tensor(labels, dtype=tf.int32)# 建立TF队列,打乱数据image, label = tf.train.slice_input_producer([imagepaths, labels],shuffle=True)# 读取数据image = tf.read_file(image)image = tf.image.decode_jpeg(image, channels=CHANNELS)# 将图像resize成规定大小image = tf.image.resize_images(image, [IMG_HEIGHT, IMG_WIDTH])# 手动归一化image = image * 1.0/127.5 - 1.0# 创建batchX, Y = tf.train.batch([image, label], batch_size=batch_size,capacity=batch_size * 8,num_threads=4)return X, Y

设置网络参数

#网络参数learning_rate = 0.001#学习率num_steps = 100#迭代次数batch_size = 128#每批大小display_step = 100#显示调试信息dropout = 0.75 # dropout保留比率X, Y = read_images(DATASET_PATH, batch_size)#读取数据集

定义网络结构:

# 创建卷积模型def conv_net(x, n_classes, dropout, reuse, is_training):# Define a scope for reusing the variableswith tf.variable_scope('ConvNet', reuse=reuse):# 第一层卷积conv1 = tf.layers.conv2d(x, 32, 5, activation=tf.nn.relu)# 最大池化conv1 = tf.layers.max_pooling2d(conv1, 2, 2)# 第二层卷积conv2 = tf.layers.conv2d(conv1, 64, 3, activation=tf.nn.relu)# 最大池化conv2 = tf.layers.max_pooling2d(conv2, 2, 2)# 拉成一维向量fc1 = tf.layers.flatten(conv2)# 全连接层fc1 = tf.layers.dense(fc1, 1024)# 应用dropoutfc1 = tf.layers.dropout(fc1, rate=dropout, training=is_training)# 输出out = tf.layers.dense(fc1, n_classes)# softmax输出out = tf.nn.softmax(out) if not is_training else outreturn out

定义训练网络和评估网络,并进行训练

#训练网络logits_train = conv_net(X, N_CLASSES, dropout, reuse=False, is_training=True)# 测试网络logits_test = conv_net(X, N_CLASSES, dropout, reuse=True, is_training=False)# 定义损失和优化器loss_op = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits_train, labels=Y))optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)train_op = optimizer.minimize(loss_op)# 评估模型correct_pred = tf.equal(tf.argmax(logits_test, 1), tf.cast(Y, tf.int64))accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))# 初始化变量init = tf.global_variables_initializer()# 保存模型参数saver = tf.train.Saver()# 开始训练with tf.Session() as sess:coord=tf.train.Coordinator()# 初始化参数sess.run(init)# 数据集队列tf.train.start_queue_runners(sess=sess,coord=coord)# 循环训练for step in range(1, num_steps+1):if step % display_step == 0:# Run optimization and calculate batch loss and accuracy_, loss, acc = sess.run([train_op, loss_op, accuracy])print("Step " + str(step) + ", Minibatch Loss= " + \"{:.4f}".format(loss) + ", Training Accuracy= " + \"{:.3f}".format(acc))else: sess.run(train_op)coord.request_stop()#请求线程结束coord.join()#等待线程结束print("Optimization Finished!")# 保存模型saver.save(sess, './cnn_mnist_model/my_tf_model')

结果

Step 100, Minibatch Loss= 0.1098, Training Accuracy= 0.969Step 200, Minibatch Loss= 0.1070, Training Accuracy= 0.969Step 300, Minibatch Loss= 0.0393, Training Accuracy= 1.000Step 400, Minibatch Loss= 0.0688, Training Accuracy= 0.984Step 500, Minibatch Loss= 0.0559, Training Accuracy= 0.992Step 600, Minibatch Loss= 0.0433, Training Accuracy= 0.984Step 700, Minibatch Loss= 0.0341, Training Accuracy= 0.992Step 800, Minibatch Loss= 0.0309, Training Accuracy= 0.984Step 900, Minibatch Loss= 0.0825, Training Accuracy= 0.969Step 1000, Minibatch Loss= 0.0211, Training Accuracy= 1.000Optimization Finished!

个人感觉相对于theano使用tensorflow的好处在于,无需自己写梯度优化了,创建模型貌似不用自己去挨个权重定义和初始化,这里就没针对每个卷积核定义变量和单独初始化,除此之外,没感觉有啥其它便利性了。 还有一个重要问题是,这个模型保存了以后,好像无法拿过来单独测试一张图片,因为这里没有函数提供额外输入,即使想调用logits_test来测试单张图片,也不好弄,因为X无法在重载模型后指定单张图片,所以还得改代码,后续再研究研究模型保存与载入。

后记

这一部分主要了解一下在TensorFlow中构建神经网络可以使用的部分函数。 我嘞个乖乖,感觉好难啊,跟Theano差不多,好底层,想脱坑转TensorLayer或者TFLearn这两个基于tensorflow的二次封装库,知乎上有对应讨论如何比较Keras, TensorLayer, TFLearn ?,貌似大部分人都推荐TL,先继续折腾TensorFlow的保存和加载模型,如果实在不行,后续去了解一下对工程实现的支持程度以及模型的保存和载入难度,再选择框架。

协助本站SEO优化一下,谢谢!
关键词不能为空
同类推荐
«    2025年12月    »
1234567
891011121314
15161718192021
22232425262728
293031
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
搜索
最新留言
文章归档
网站收藏
友情链接