我做了一个基本的自定义估计器,用于对短文本进行分类。
与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是标签数。我可以再次调整张量的大小。但是我觉得这可能会浪费时间。
而且,由于我的天真,所以这种方法行不通。我必须问,如何正确地做。
答案 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)