在七月份对传统机器学习方法的总览学习之后,我这半个月都在学习如何使用TensorFlow框架进行深度学习,最近进行了一个小的项目——验证码识别,期间踩了不少坑,不得不说TensorFlow算是我用过的较难的框架了,在这里进行总结,和大家分享。
处理图像问题
使用卷积神经网络处理图片前,一般要先进行一些图片处理,将它归一化,例如图像的大小、色调等,可以使用PIL库。
from PIL import Image
img = Image.open(path+name)
img = img.resize((width,height))
img.save(after_path+name)
文件大小问题
一般为了统一读取文件格式,会将数据处理成tfrecords的形式,但很多文件在转化的过程中会变大,例如我将60000张验证码图片转化为tfrecords格式,由174M转化成了1.4G,原因在于tfrecords格式是int64存储,但是jpg格式是int8格式存储
def get_example(width,height,label,pixels):
example = tf.train.Example(features=tf.train.Features(feature={
'width': _int64_feature(width),
'height': _int64_feature(height),
'label': _bytes_feature(label),
'pixels_raw': _bytes_feature(pixels)
}))
return example
文件格式问题
为了使tfrecords格式文件能够顺利解码为np.array,可以使用np.array自带的转化函数。
label = np.array(convert_label_s2n(label)).tostring()
width = size[0]
height = size[1]
pixels = np.array((list(img.getdata()))).tostring()
卷积大小问题
神经网络卷积层使用conv2d来进行计算,其中一个坑是padding,如果padding选择‘SAME’,则输出层和输入层图像大小相等,这种方法是补全0进行卷积的。如果padding选择‘VALID’,则可以使用公式进行计算输出层图像大小。 $$ N = \frac {W-F} {s} + 1(向下取整)\\ 输入图片大小 W×W, Filter大小 F×F, 步长 S, padding的像素数 P, $$
conv3 = tf.nn.conv2d(pool2, conv3_weights, strides=[1, 1, 1, 1], padding='SAME')
文件读取问题
为了读取一个batch的tfrecords格式文件,有以下两种初始法,第一种会导致读取的缓冲区文件不够的错误:
“andom_shuffle_queue’ is closed and has insufficient elements”
错误读法如下:
# 创建文件列表,通过文件列表创建输入文件队列
files = tf.train.match_filenames_once("./复杂数据集/训练数据集.tfrecords“")
filename_queue = tf.train.string_input_producer(files, shuffle=False)
# 解析TFRecord文件里的数据。
# 读取文件。
reader = tf.TFRecordReader()
_, serialized_example = reader.read(filename_queue)
读取文件。
正确读法如下:
reader = tf.TFRecordReader()
filename_queue = tf.train.string_input_producer(["./复杂数据集/训练数据集.tfrecords"])
_,serialized_example = reader.read(filename_queue)
文件读取问题(2)
读取tfrecords文件要初始化local和global两种初始变量,并且在结束后要关闭队列,否则都会报错
with tf.Session(config=config) as sess:
sess.run(tf.local_variables_initializer())
sess.run(tf.global_variables_initializer())
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(coord=coord)
''''''
# 训练网络的代码
''''''
coord.request_stop()
coord.join(threads)
限制CPU个数
为了防止在训练神经网络时候CPU被占满,可以限制CPU使用个数,例如我的四核计算机一般限制三个CPU进行训练,另一个支持其他进程。
# 限制cpu个数(主要是防止CPU占用率过高,电脑无法操作)
cpu_num = int(os.environ.get('CPU_NUM', 3))
config = tf.ConfigProto(device_count={"CPU": cpu_num},
inter_op_parallelism_threads=cpu_num,
intra_op_parallelism_threads=cpu_num,
log_device_placement=True)
with tf.Session(config=config) as sess:
Tensor和np.array的转化
在训练神经网络时,这两种格式的变量经常要进行转化,可以如下进行
#转化为np.array
img_numpy=img.eval(session=sess)
print("out2=",type(img_numpy))
#转化为tensor
img_tensor= tf.convert_to_tensor(img_numpy)
类型和形状转换
pixels = tf.cast(pixels, tf.float32)
pixels=tf.reshape(pixels,[WIDTH,HEIGHT,1])
查看更多
所有的文章都会在我的博客和我的知乎专栏同步进行更新,欢迎阅读