TensorFlow的高阶接口Estimator的使用(2)——自定义CNN模型

在上一篇文章中,我们使用了Estimator自带的LinearClassfier,本文将会重写6.3的程序,使用自定义的Estimator。

参考[1],构建一个estimator,主要还是两部分,第一部分是model function, 第二部分是input function,其中input function跟上一篇文章相同,所以这里我会主要说一下model function。其实构建方法也很简单,主要就是构建一个网络,和一个loss(损失函数)。

model_fn会有三个参数,features,labels以及mode。mode是一个枚举类型的参数,分为三种,分别是TRAIN EVAL 和PERDICT,很遗憾,原作者没有写这个,我们会在本文中弥补这个遗憾。

一个Estimator的skeleton(骨架)应该是这样:


def model_fn(features, labels, mode, params):
   
# 满足以下逻辑:
   
# 1. 通过TensorFlow的operations来配置model
   
# 2. 定义training/evaluation的损失函数
   
# 3. 定义training用的ptimizer
   
# 4. 生成预测(predictions)
   
# 5. 返回 EstimatorSpec 对象
   
return EstimatorSpec(mode, predictions, loss, train_op, eval_metric_ops)


完整的代码如下,欢迎讨论


import glob
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf

datadir='data/cifar-10-batches-bin/'

N_CLASS=10 #类别数目
X_FEATURE = 'x'  # name of the input feature

plt.ion()
G = glob.glob (datadir + '*.bin')
A = np.fromfile(G[0],dtype=np.uint8).reshape([10000,3073])
labels = A [:,0]
images = A [:,1:].reshape([10000,3,32,32]).transpose (0,2,3,1)
plt.imshow(images[15])
images_unroll = A [:,1:]

def max_pool_2x2(tensor_in):
	return tf.nn.max_pool(tensor_in,  ksize= [1,2,2,1], strides= [1,2,2,1], padding='SAME')

def conv_model (features, labels,mode):
    #这里的参数必须是这样
    X=features[X_FEATURE]
    X= tf. reshape(X, [-1, 32, 32, 3])
    with tf.variable_scope('conv_layer1'):
        h_conv1=tf.layers.conv2d(X, filters=16,  kernel_size=[5,5],  activation=tf.nn.relu)
        h_pool1=max_pool_2x2(h_conv1)#print (h_pool1)
    with tf.variable_scope('conv_layer2'):
        h_conv2=tf.layers.conv2d(h_pool1, filters=16, kernel_size=[5,5], activation=tf.nn.relu)
    #print (h_conv2)
    h_pool2=max_pool_2x2(h_conv2)
    #h_pool2_flat = tf.reshape(h_pool2,  [-1,8*8*16 ]) #this line not work becasue there no batch_size here
    #h_fc1 = tf.contrib.layers.stack(h_pool2_flat, tf.contrib.layers.fully_connected ,[96,48], activation_fn=tf.nn.relu )
    net_shape = h_pool2.get_shape().as_list()
    h_pool2_flat = tf.reshape(h_pool2, [-1, net_shape[1] * net_shape[2] * net_shape[3]])
    
    logits = tf.layers.dense(h_pool2_flat,N_CLASS,activation=None)
    predicted_classes = tf.argmax(logits, 1)
    if mode == tf.estimator.ModeKeys.PREDICT:
        predictions = {
            'class': predicted_classes,
            'prob': tf.nn.softmax(logits)
        }
        return tf.estimator.EstimatorSpec(mode, predictions=predictions)
    
      # Compute loss.
    loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)
    
      # Create training op.
    if mode == tf.estimator.ModeKeys.TRAIN:
        optimizer = tf.train.AdagradOptimizer(learning_rate=0.01)
        train_op = optimizer.minimize(loss, global_step=tf.train.get_global_step())
        return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op)
    
      # Compute evaluation metrics.
    eval_metric_ops = {
          'accuracy': tf.metrics.accuracy(
              labels=labels, predictions=predicted_classes)
      }
    return tf.estimator.EstimatorSpec(
          mode, loss=loss, eval_metric_ops=eval_metric_ops)



images = np.array(images,dtype=np.float32)
classifier = tf.estimator.Estimator(model_fn=conv_model)

train_input_fn = tf.estimator.inputs.numpy_input_fn(
      x={X_FEATURE: images},
      y=labels.astype(np.int32),
      batch_size=100,
      num_epochs=30,
      shuffle=True)
test_input_fn = tf.estimator.inputs.numpy_input_fn(
      x={X_FEATURE: images},
      y=labels.astype(np.int32),
      num_epochs=1,
      shuffle=False)

classifier.train(input_fn=train_input_fn,steps=10000)
score =classifier.evaluate(input_fn=test_input_fn)
print ('Accuracy: {0:f}'.format(score['accuracy']))






Reference

[1] 构建Estimator

[2] resnet.py