Tensorflow v1.10: armazenar imagens como sequências de bytes ou por canal?
Sabe-se que, no momento, a documentação do TF Record deixa algo a desejar.
Minha pergunta é em relação ao que é ideal para armazenar:
uma sequência,suas probabilidades de classe por elemento ealgumas informações (de contexto?) (por exemplo, nome da sequência)como um registro TF.
Nomeadamente, essas perguntas consideram o armazenamento das probabilidades de sequência e classe como canais versus como uma sequência de bytes e se a meta-informação deve ou não entrar como recursos de umtf.train.Example
ou como o contexto de umtf.train.SequenceExample
. (veja as perguntas na parte inferior).
Por exemplo, vamos assumir minha sequência de looks como esta
seq = [
# el1, el2
[ 0, 1 ], # channel 1
[ 0, 1 ] # channel 2
]
ou seja, é uma sequência de 2 canais defixo length (neste exemplo, 2) em que os valores podem ser apenas um valor inteiro.
e que temos três classes para as quais estamos tentando segmentar a sequência em
cls_probs = [
#cls1, cls2, cls3
[0 , 0.9 , 0.1 ], # class probabilities element 1
[0 , 0.1 , 0.9 ] # class probabilities element 2
]
onde de fato ambosseq
ecls_probs
estãonumpy.array
s.
Apenas a rederequer Essa informação. No entanto, também tenho alguns metadados que gostaria de manter com a sequência.
por exemplo.
meta = {
'name': 'my_seq', # safer to keep this with the data rather than as file name
'meta_val_1': 100, # not used by network, but may be useful when evaluating network's predictions for this particular sequence
'meta_val_2': 10
}
Fazendo TF Recordtf.train.ExampleEntão eu tenho várias maneiras de construir meutf.train.Example
:
example = tf.train.Example(
features = tf.train.Features(
feature = {
'channel_1': tf.train.Feature(int64_list=tf.train.Int64List(value=seq[:,0])),
'channel_2': tf.train.Feature(int64_list=tf.train.Int64List(value=seq[:,1])),
'class_1' : tf.train.Feature(float_list=tf.train.FloatList(value=cls_probs[:,0])),
'class_2' : tf.train.Feature(float_list=tf.train.FloatList(value=cls_probs[:,1])),
'class_3' : tf.train.Feature(float_list=tf.train.FloatList(value=cls_probs[:,2])),
'name' : tf.train.Feature(bytes_list=tf.train.BytesList(value=[f'{meta["name"]}'.encode('utf-8')])),
# should these be FloatList even though it is just a single value?
# should these be included here if they are not used by the network?
'val_1' : tf.train.Feature(float_list=tf.train.FloatList(value=[f'{meta["meta_val_1"]}'])),
'val_2' : tf.train.Feature(float_list=tf.train.FloatList(value=[f'{meta["meta_val_2"]}'])),
})
)
Ondef'{variable}'.encode('utf-8')
é o atualmente não sugeridofb'<string>'
(Nota:f-strings
só funciona com python3.6 +).
Esse formato é um pouco agradável, pois cada canal de sequência é explícito. No entanto, também é detalhado e requer pré-processamento quando carregado para ser alimentado na rede.
Como cordaou, eu poderia despejar minha matriz em uma string
example = tf.train.Example(
features = tf.train.Features(
feature = {
'sequence' : tf.train.Feature(bytes_list=tf.train.BytesList(value=seq.tostring())),
'cls_probs': tf.train.Feature(bytes_list=tf.train.BytesList(value=cls_probs.tostring())),
# ... see encoding of meta values from above
})
)
tf.train.SequenceExampleOs registros TF também aceitam outro formulário:tf.train.SequenceExample
. SequenceExample
espera recursos de contexto e uma lista ordenada de recursos sem nome.
Então reestruturação acima é comocanais exemplo:
example = tf.train.SequenceExample(
context = tf.train.Features(
feature = {
'Name' : tf.train.Feature(bytes_list=tf.train.BytesList(value=[f'{meta["name"]}'.encode('utf-8')])),
'Val_1': tf.train.Feature(float_list=tf.train.FloatList(value=[f'{meta["meta_val_1"]}'])),
'Val_2': tf.train.Feature(float_list=tf.train.FloatList(value=[f'{meta["meta_val_2"]}'])),
}
),
feature_lists = tf.train.FeatureLists(
feature_list = {
'sequence': tf.train.FeatureList(
feature = [
tf.train.Feature(int64_list=tf.train.Int64List(value=seq[:,0])),
tf.train.Feature(int64_list=tf.train.Int64List(value=seq[:,1])),
]
),
'class_probabilities': tf.train.FeatureList(
feature = [
tf.train.Feature(float_list=tf.train.FloatList(value=cls_probs[:,0])),
tf.train.Feature(float_list=tf.train.FloatList(value=cls_probs[:,1])),
tf.train.Feature(float_list=tf.train.FloatList(value=cls_probs[:,2]))
]
)
}
)
)
Como cordaDa mesma forma, podemos criar o comocorda exemplo:
example = tf.train.SequenceExample(
context = tf.train.Features(
# see above
),
feature_lists = tf.train.FeatureLists(
feature_list = {
'sequence': tf.train.FeatureList(
feature = [
tf.train.Feature(bytes_list=tf.train.BytesList(value=seq.tostring()))
]
),
'class_probabilities': tf.train.FeatureList(
feature = [
tf.train.Feature(bytes_list=tf.train.BytesList(value=cls_probs.tostring()))
]
)
}
)
)
QuestõesAqui eu dei um M.W.E. de como alguém poderia construir um exemplo (pronto para ser exportado para um Registro TF) como ambostf.train.Example
etf.train.SequenceExample
. Além disso, demonstrei como fazer isso por canal ou descartando como uma sequência de bytes. Ambos os métodos (como canais / como seqüências de caracteres) incluem as meta informações no exemplo.
Assim, minhas perguntas são:
qual o caminho (como canais / como sequência) de armazenamento é mais ideal (para leitura, gravação, reutilização etc.)?
dada a meta informação que deve ser mantida com o exemplo, é melhor usartf.train.Example
e armazenar as informações meta como recursos lá? ou usetf.train.SequenceExample
e armazenar as meta informações no argumento de contexto?
Alguém sabe se existem vantagens / desvantagens notáveis para qualquer uma dessas quatro estratégias?
Para aqueles que desejam testar isso em dados maiores e menos fictícios, algumas funções para produzir esse código podem ser encontradasabaixo
Por fim, gostaria de destacar issopost médio que elabora muito os documentos do TF.