如何将卷积层添加到自定义估算器

时间:2018-10-03 17:31:36

标签: python python-3.x tensorflow neural-network conv-neural-network

我做了一个基本的自定义估计器,用于对短文本进行分类。

与www.tensorflow.org上的教程相比,它有了很大的提升,只做了很少的改动,主要是为了更容易地进行调整。

功能列是categorical_column_with_hashbucket,包装在embedding_column中。

https://www.tensorflow.org/api_docs/python/tf/feature_column/categorical_column_with_hash_bucket

https://www.tensorflow.org/api_docs/python/tf/feature_column/embedding_column

def text_classifier(
features, # This is batch_features from input_fn
labels,   # This is batch_labels from input_fn
mode,     # An instance of tf.estimator.ModeKeys
params):  # Additional configuration

# Use `input_layer` to apply the feature columns.

net = tf.feature_column.input_layer(
    features, 
    feature_columns=params['feature_columns'])

if params['dropout']:
            net = tf.layers.dropout(net,rate=0.0001,training=True)
# Build the hidden layers, sized according to the 'hidden_units' param.
try:
    activation=params['activation']
except KeyError:
    activation=tf.nn.relu
if 'hidden_dense_units' in params:
    for units in params['hidden_dense_units']:
        net = tf.layers.dense(net,
                    units=units,
                    activation=activation,
                    kernel_initializer=tf.glorot_uniform_initializer()
                    )
        #Dropout layer
        if params['dropout']:
            net = tf.layers.dropout(net,rate=0.5,training=True)
        #Normalization
        if params['normalization']:
            net = tf.layers.batch_normalization(
                net,
                momentum=0.999,
                training=True
                )

# Compute logits (1 per class).
logits = tf.layers.dense(net, params['n_classes'], activation=None)

# Compute predictions.
predicted_classes = tf.argmax(logits, 1)
if mode == tf.estimator.ModeKeys.PREDICT:
    predictions = {
        'class_ids': predicted_classes[:, tf.newaxis],
        'probabilities': tf.nn.softmax(logits),
        'logits': logits,
    }
    return tf.estimator.EstimatorSpec(mode, predictions=predictions)

# Compute loss. 
loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)

# Compute evaluation metrics.
accuracy = tf.metrics.accuracy(labels=labels,
                                predictions=predicted_classes,
                                name='acc_op')

metrics = {'accuracy': accuracy}

tf.summary.scalar('accuracy', accuracy[1])

if mode == tf.estimator.ModeKeys.EVAL:
    return tf.estimator.EstimatorSpec(
        mode, loss=loss, eval_metric_ops=metrics)

#Training OP
assert mode == tf.estimator.ModeKeys.TRAIN

#Initiating optimizer
try:
    optimizer = params['optimizer']
except KeyError:
    optimizer = tf.train.AdamOptimizer(learning_rate = 0.001)

train_op = optimizer.minimize(loss, global_step=tf.train.get_global_step())

return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op)

达到预期的最高性能后,测试数据集的精度约为0.6。我决定从Tensorflow库中添加一维卷积层。

https://www.tensorflow.org/api_docs/python/tf/layers/conv1d

不幸的是,文档没有指定,它需要3维张量作为输入。如果我仅使用input_layer作为输入,例如这样的话:

net = tf.layers.conv1d(net,filters=1,kernel_size=1)

我收到以下异常:

ValueError: Input 0 of layer conv1d_1 is incompatible with the layer: expected ndim=3, found ndim=2. Full shape received: [None, 1024]

1024正在嵌入维度btw,但是大小无关紧要,该过程仍然会崩溃。

我可以扩展张量,像这样添加尺寸:

more_dim = tf.expand_dims(input=net,axis=-1)
net = tf.layers.conv1d(more_dim,filters=1,kernel_size=1)

但这一次只给了我一个例外,这次是在计算softmax交叉熵损失时:

ValueError("Can not squeeze dim[2], expected a dimension of 1, got 18 for 'sparse_softmax_cross_entropy_loss/remove_squeezable_dimensions/Squeeze' (op: 'Squeeze') with input shapes: [?,1024,18].",)

最后一个维度18是标签数。我可以再次调整张量的大小。但是我觉得这可能会浪费时间。

而且,由于我的天真,所以这种方法行不通。我必须问,如何正确地做。

1 个答案:

答案 0 :(得分:2)

我认为Tensorflow需要额外的渠道维度。试试

net = tf.expand_dims(net, -1) # Adding a channel as last dimension.
net = tf.layers.conv1d(net,filters=1,kernel_size=1)