Я пытаюсь реализовать многомерную последовательность для последовательности модели Semi Supervised Learning, используя пакет Neural Structured Learning (NSL) Tensorflow. В моей модели используются слои GRU, где входные данные содержат три разных функции, а выходные данные - две разные функции. Итак, в этом случае форма ввода - float (11,3), а форма вывода - int (11,2).
Я реализовал свою модель NSL, следуя этому учебному руководству . Моего понимания tfrecords, структуры данных nsl и регуляризации графов недостаточно. Таким образом, я изо всех сил пытался построить правильную подготовку данных. Итак, я прошу здесь помочь построить правильную структуру данных.
Я думаю, что первая часть работает нормально. Мне удалось без проблем создавать вложения, графики и обучающие данные nls. Я сделал искусственные данные для этой цели и разделил их на форму (11,5), где первые 3 функции являются входными данными, а остальные данные представляют собой целочисленные векторные метки.
import numpy as np
import math
import neural_structured_learning as nsl
import tensorflow as tf
import tensorflow_hub as hub
# Resets notebook state
tf.keras.backend.clear_session()
pretrained_embedding = 'https://tfhub.dev/google/tf2-preview/gnews-swivel-20dim/1'
hub_layer = hub.KerasLayer(
pretrained_embedding, input_shape=[], dtype=tf.string, trainable=True)
def generate_train_dataset():
n = np.linspace(0,100,1000)
data = np.zeros([1000,5])
data[:,0] = np.sin(n) +np.random.randn(1000)
data[:,1] = np.cos(n) +np.random.randn(1000)
data[:,2] = np.cosh(n) + np.random.randn(1000)
for i in range(100):
data[i:i+9, 3] = 1
data[i-5:i + 4, 4] = 1
return data
data = generate_train_dataset()
def _int64_feature(value):
"""Returns int64 tf.train.Feature."""
return tf.train.Feature(int64_list=tf.train.Int64List(value=value.tolist()))
def _bytes_feature(value):
"""Returns bytes tf.train.Feature."""
return tf.train.Feature(
bytes_list=tf.train.BytesList(value=[value.encode('utf-8')]))
def _float_feature(value):
"""Returns float tf.train.Feature."""
return tf.train.Feature(float_list=tf.train.FloatList(value=value.tolist()))
def create_embedding_example(data_seq, record_id):
"""Create tf.Example containing the sample's embedding and its ID."""
# Shape = [batch_size,].
layer = tf.as_string(tf.reshape(data_seq, shape=[-1, ]),precision=9)
sentence_embedding = hub_layer(layer)
# Flatten the sentence embedding back to 1-D.
sentence_embedding = tf.reshape(sentence_embedding, shape=[-1])
features = {
'id': _bytes_feature(str(record_id)),
'embedding': _float_feature(sentence_embedding.numpy())
}
return tf.train.Example(features=tf.train.Features(feature=features))
def create_embeddings(data, output_path, starting_record_id):
record_id = int(starting_record_id)
#drops labels, labes idx = (3,4)
data_seqs = np.zeros((989,11,3))
row = 0
for i in range(11,1000):
data_seqs[row] = data[i-11:i,0:3]
row = row + 1
with tf.io.TFRecordWriter(output_path) as writer:
for data_seq in data_seqs:
example = create_embedding_example(data_seq, record_id)
record_id = record_id + 1
writer.write(example.SerializeToString())
return record_id
# Persist TF.Example features containing embeddings for training data in
# TFRecord format.
create_embeddings(data, 'tmp/imdb/embeddings.tfr', 0)
##################################################################################
nsl.tools.build_graph(['tmp/imdb/embeddings.tfr'],
'tmp/imdb/graph_99.tsv',
similarity_threshold=0.99)
def create_example(data_seq, record_id):
"""Create tf.Example containing the sample's word vector, label, and ID."""
features = {
'id': _bytes_feature(str(record_id)),
'sin': _float_feature(data_seq[:, 0]),
'cos': _float_feature(data_seq[:, 1]),
'cosh': _float_feature(data_seq[:, 2]),
'label_1': _int64_feature(np.int64(data_seq[:,3])),
'label_2': _int64_feature(np.int64(data_seq[:,4])),
}
return tf.train.Example(features=tf.train.Features(feature=features))
def create_records(data, record_path, starting_record_id):
record_id = int(starting_record_id)
data_seqs = np.zeros((989, 11, 5))
row = 0
for i in range(11, 1000):
data_seqs[row] = data[i - 11:i, :]
row = row + 1
with tf.io.TFRecordWriter(record_path) as writer:
for row in range(data_seqs.shape[0]):
#for word_vector, label in zip(word_vectors, labels):
example = create_example(data_seqs[row,:], record_id)
record_id = record_id + 1
writer.write(example.SerializeToString())
return record_id
# Persist TF.Example features (word vectors and labels) for training and test
# data in TFRecord format.
next_record_id = create_records(data,'tmp/imdb/train_data.tfr', 0)
nsl.tools.pack_nbrs(
'tmp/imdb/train_data.tfr',
'',
'tmp/imdb/graph_99.tsv',
'tmp/imdb/nsl_train_data.tfr',
add_undirected_edges=True,
max_nbrs=3)
Здесь я обнаружил проблемы. Я реализовал несколько разных версий, но ни одна из них не работает. Вот одна из моих версий, которая не работает.
NBR_FEATURE_PREFIX = 'NL_nbr_'
NBR_WEIGHT_SUFFIX = '_weight'
class HParams(object):
"""Hyperparameters used for training."""
def __init__(self):
### dataset parameters
self.num_classes = 2
self.max_seq_length = 256
self.vocab_size = 10000
### neural graph learning parameters
self.distance_type = nsl.configs.DistanceType.L2
self.graph_regularization_multiplier = 0.1
self.num_neighbors = 2
### model architecture
self.num_embedding_dims = 16
self.num_lstm_dims = 64
self.num_fc_units = 64
### training parameters
self.train_epochs = 10
self.batch_size = 128
### eval parameters
self.eval_steps = None # All instances in the test set are evaluated.
HPARAMS = HParams()
def make_dataset(file_path, training=False):
"""Creates a `tf.data.TFRecordDataset`.
Args:
file_path: Name of the file in the `.tfrecord` format containing
`tf.train.Example` objects.
training: Boolean indicating if we are in training mode.
Returns:
An instance of `tf.data.TFRecordDataset` containing the `tf.train.Example`
objects.
"""
def pad_sequence(sequence, max_seq_length):
"""Pads the input sequence (a `tf.SparseTensor`) to `max_seq_length`."""
pad_size = tf.maximum([0], max_seq_length - tf.shape(sequence)[0])
padded = tf.concat(
[sequence.values,
tf.fill((pad_size), tf.cast(0, sequence.dtype))],
axis=0)
# The input sequence may be larger than max_seq_length. Truncate down if
# necessary.
return tf.slice(padded, [0], [max_seq_length])
def parse_example(example_proto):
"""Extracts relevant fields from the `example_proto`.
Args:
example_proto: An instance of `tf.train.Example`.
Returns:
A pair whose first value is a dictionary containing relevant features
and whose second value contains the ground truth labels.
"""
# The all features has length of 11.
feature_spec = {
'sin': tf.io.FixedLenSequenceFeature(11,tf.float32,allow_missing=True),
'cos': tf.io.FixedLenSequenceFeature(11,tf.float32,allow_missing=True),
'cosh': tf.io.FixedLenSequenceFeature(11,tf.float32,allow_missing=True),
'label_1': tf.io.FixedLenSequenceFeature(11,tf.int64,allow_missing=True),
'label_2': tf.io.FixedLenSequenceFeature(11,tf.int64,allow_missing=True),
}
# We also extract corresponding neighbor features in a similar manner to
# the features above during training.
if training:
for i in range(2):
nbr_feature_key = '{}{}_{}'.format(NBR_FEATURE_PREFIX, i, 'cos')
feature_spec[nbr_feature_key] = tf.io.FixedLenSequenceFeature([11],dtype=tf.float32,allow_missing=True)
nbr_feature_key = '{}{}_{}'.format(NBR_FEATURE_PREFIX, i, 'sin')
feature_spec[nbr_feature_key] = tf.io.FixedLenSequenceFeature([11],dtype=tf.float32,allow_missing=True)
nbr_feature_key = '{}{}_{}'.format(NBR_FEATURE_PREFIX, i, 'cosh')
feature_spec[nbr_feature_key] = tf.io.FixedLenSequenceFeature([11],dtype=tf.float32,allow_missing=True)
nbr_weight_key = '{}{}{}'.format(NBR_FEATURE_PREFIX, i,NBR_WEIGHT_SUFFIX)
# We assign a default value of 0.0 for the neighbor weight so that
# graph regularization is done on samples based on their exact number
# of neighbors. In other words, non-existent neighbors are discounted.
feature_spec[nbr_weight_key] = tf.io.FixedLenFeature(
[1], tf.float32, default_value=tf.constant([0.0]))
#features = tf.io.parse_single_example(example_proto, feature_spec)
features = tf.io.parse_single_sequence_example(example_proto, feature_spec)
# I think word padding isn't needed in this case. I might be wrong
#features['words'] = pad_sequence(features['words'], HPARAMS.max_seq_length)
#if training:
# for i in range(2):
# nbr_feature_key = '{}{}_{}'.format(NBR_FEATURE_PREFIX, i, 'words')
# features[nbr_feature_key] = pad_sequence(features[nbr_feature_key],HPARAMS.max_seq_length)
labels = tf.stack([tf.reshape(features.pop('label_1'), [11]), \
tf.reshape(features.pop('label_2'), [11])],axis=1)
return features, labels
dataset = tf.data.TFRecordDataset([file_path])
if training:
dataset = dataset.shuffle(100)
dataset = dataset.map(parse_example)
dataset = dataset.batch(64)
return dataset
train_dataset = make_dataset('tmp/imdb/nsl_train_data.tfr', True)
def make_gru_model():
input = tf.keras.layers.Input(shape=(11, 3))
x = tf.keras.layers.GaussianNoise(0.3)(input)
x = tf.keras.layers.GRU(6, reset_after=True,return_sequences=True)(x)
x = tf.keras.layers.Dropout(0.1)(x)
x = tf.keras.layers.GaussianNoise(0.3)(x)
x = tf.keras.layers.GRU(6 // 2, reset_after=True,return_sequences=True)(x)
x = tf.keras.layers.Dense(2, activation='sigmoid')(x)
model = tf.keras.Model(input, x)
return model
model = make_gru_model()
#Graph regularization
validation_fraction = 0.9
validation_size = int(validation_fraction *
int(989 / HPARAMS.batch_size))
print(validation_size)
validation_dataset = train_dataset.take(validation_size)
train_dataset = train_dataset.skip(validation_size)
graph_reg_config = nsl.configs.make_graph_reg_config(
max_neighbors=HPARAMS.num_neighbors,
multiplier=HPARAMS.graph_regularization_multiplier,
distance_type=HPARAMS.distance_type,
sum_over_axis=-1)
graph_reg_model = nsl.keras.GraphRegularization(model,graph_reg_config)
graph_reg_model.compile(
optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
graph_reg_history = graph_reg_model.fit(
train_dataset,
validation_data=validation_dataset,
epochs=HPARAMS.train_epochs,
verbose=1)
Итак, проблема заключается в правильной подготовке данных для нейронной сети. Текущий код дает следующее сообщение об ошибке:
ValueError: Unsupported FixedLenSequenceFeature FixedLenSequenceFeature(shape=[11], dtype=tf.float32, allow_missing=True, default_value=None).
Это мой первый вопрос в Stackoverflow, поэтому я мог что-то пропустить. Скажите, пожалуйста, если я забыл добавить важную информацию для решения этой проблемы.