BrainScript CNTK Leitor de Formato de Texto
Esta página documenta o CNTKTextFormatReader do ponto de vista do BrainScript, mas os usuários do Python também podem aprender lendo este documento. Os conceitos, parâmetros e padrões são todos iguais.
O CNTKTextFormatReader (posteriormente simplesmente CTF Reader) foi projetado para consumir dados de texto de entrada formatados de acordo com a especificação abaixo. Ele dá suporte aos seguintes recursos principais:
- Vários fluxos de entrada (entradas) por arquivo
- Entradas esparsas e densas
- Sequências de comprimento variável
formato de texto CNTK (CTF)
Cada linha no arquivo de entrada contém um exemplo para uma ou mais entradas. Como (explicitamente ou implicitamente) cada linha também está anexada a uma sequência, ela define uma ou mais <relações de sequência, entrada e exemplo> . Cada linha de entrada deve ser formatada da seguinte maneira:
[Sequence_Id](Sample or Comment)+
onde
Sample=|Input_Name (Value )*
Comment=|# some content
- Cada linha começa com uma ID de sequência e contém um ou mais exemplos (em outras palavras, cada linha é uma coleção não ordenada de amostras).
- A ID da sequência é um número. Ele pode ser omitido, caso em que o número de linha será usado como a ID da sequência.
- Cada exemplo é efetivamente um par chave-valor que consiste em um nome de entrada e o vetor de valor correspondente (o mapeamento para dimensões mais altas é feito como parte da própria rede).
- Cada exemplo começa com um símbolo de pipe (
|
) seguido pelo nome de entrada (sem espaços), seguido por um delimitador de espaço em branco e, em seguida, uma lista de valores. - Cada valor é um número ou um número prefixado por índice para entradas esparsas.
- As guias e os espaços podem ser usados de forma intercambiável como delimitadores.
- Um comentário começa com um pipe imediatamente seguido por um símbolo de hash:
|#
, em seguida, seguido pelo conteúdo de fato (corpo) do comentário. O corpo pode conter caracteres, no entanto, um símbolo de pipe dentro do corpo precisa ser escapado acrescentando o símbolo de hash a ele (veja o exemplo abaixo). O corpo de um comentário continua até o fim da linha ou o próximo pipe não escapado, o que vier primeiro.
Exemplo simples
Este exemplo baseia-se em um conjunto mínimo de parâmetros e opções de formato.
Para usar o Leitor de CTF, defina a readerType
CNTKTextFormatReader
seção de leitor da configuração do CNTK:
...
reader = [
readerType = "CNTKTextFormatReader"
file = "c:\mydata\SampleInput.txt" # See the second example for Linux path example
# IMPORTANT!
# All inputs are grouped within "input" sub-section.
input = [
A = [
dim = 5
format = "dense"
]
B = [
dim = 1000000
format = "sparse"
]
C = [
dim = 1
format = "dense"
]
]
]
# the rest of the cntk config ...
(Esse fragmento, bem como outros exemplos de NDL neste documento, apresentam apenas reader
a seção, omitindo o restante da configuração de CNTK; consulte o final desta página para obter ponteiros para um conjunto de redes de exemplo completas e os conjuntos de dados correspondentes)
O Leitor de CTF requer o seguinte conjunto de parâmetros:
file
- caminho para o arquivo com o conjunto de dados.input
– sub-seção definindo entradas identificadas por nomes de entrada (A
B
eC
no exemplo acima). Em cada entrada, os seguintes parâmetros necessários devem ser especificados:format
– especifica o tipo de entrada. Deve serdense
ousparse
dim
- especifica a dimensão do vetor de valor de entrada (para entrada densa , isso corresponde diretamente ao número de valores em cada amostra , pois isso representa o limite superior no intervalo de valores de índice possíveis).
Os dados de entrada correspondentes à configuração do leitor acima devem ter esta aparência:
|B 100:3 123:4 |C 8 |A 0 1 2 3 4 |# a CTF comment
|# another comment |A 0 1.1 22 0.3 54 |C 123917 |B 1134:1.911 13331:0.014
|C -0.001 |# a comment with an escaped pipe: '|#' |A 3.9 1.11 121.2 99.13 0.04 |B 999:0.001 918918:-9.19
Observe o seguinte sobre o formato de entrada:
|Input_Name
identifica o início de cada exemplo de entrada. Esse elemento é obrigatório e é seguido pelo vetor de valor correspondente.- Vetor denso é apenas uma lista de valores de ponto flutuante; vetor esparso é uma lista de
index:value
tuplas. - As guias e os espaços são permitidos como delimitadores de valor (dentro de vetores de entrada), bem como delimitadores de entrada (entre entradas).
- Cada linha separada constitui uma "sequência" de comprimento 1 (sequências de comprimento variável "Real" são explicadas no exemplo estendido abaixo).
- Cada identificador de entrada só pode aparecer uma vez em uma única linha (que se traduz em um exemplo por requisito de entrada por linha ).
- A ordem dos exemplos de entrada dentro de uma linha NÃO é importante (conceitualmente, cada linha é uma coleção não ordenada de pares chave-valor)
- Cada linha bem formada deve terminar com símbolos "Feed de Linha"
\n
ou "Retorno de Carro, Feed\r\n
de Linha".
Exemplo estendido
Este exemplo apresenta todos os parâmetros de configuração possíveis e mostra várias opções de formato de entrada. Consulte as tabelas abaixo para obter a descrição completa dos parâmetros de configuração usados neste exemplo.
...
precision="double"
reader = [
readerType = "CNTKTextFormatReader"
file = "/home/mydata/SampleInput.txt" # See the first example for Windows style path example
randomize = true
randomizationWindow = 30
skipSequenceIds = false
maxErrors = 100
traceLevel = 2
chunkSizeInBytes = 1024
keepDataInMemory = true
frameMode = false
input = [
Some_very_long_input_name = [
alias = "a"
dim = 3
format = "dense"
]
Some_other_also_very_long_input_name = [
alias = "b"
dim = 2
format = "dense"
]
]
]
# the rest of the cntk config ...
Com um leitor de composição, ele gostaria do seguinte:
reader = {
verbosity = 0 ;
randomize = true;
randomizationWindow=30
deserializers = ({
type = "CNTKTextFormatDeserializer" ; module = "CNTKTextFormatReader"
file = "/home/mydata/SampleInput.txt" # See the first example for Windows style path example
maxErrors = 100
skipSequenceIds = false
traceLevel = 2
input = {
qu1fea = {alias = "qui"; dim = 95589; format = "sparse"}
qu2fea = {alias = "quj"; dim = 95589; format = "sparse"}
pairweight = {alias = "wij"; dim = 1; format = "dense"}
}
})
}
O arquivo de entrada correspondente pode, em seguida, olhar aproximadamente da seguinte maneira:
100 |a 1 2 3 |b 100 200
100 |a 4 5 6 |b 101 201
100 |b 102983 14532 |a 7 8 9
100 |a 7 8 9
200 |b 300 400 |a 10 20 30
333 |b 500 100
333 |b 600 -900
400 |a 1 2 3 |b 100 200
|a 4 5 6 |b 101 201
|a 4 5 6 |b 101 201
500 |a 1 2 3 |b 100 200
Todas as opções discutidas no exemplo acima ainda se aplicam aqui. Além disso, introduzimos dois recursos adicionais:
Aliases de nome de entrada
Os nomes de entrada podem ser arbitrários e, portanto, repeti-los em todo o arquivo de entrada pode não ser eficiente em espaço. Para atenuar isso, o conjunto de dados pode usar "aliases" em vez de nomes de entrada completos. Em seguida, os aliases precisam ser especificados em cada sub-subseção de entrada. Em nosso exemplo, o conjunto de dados usa aliases a
e b
, que são mapeados para "Some_very_long_input_name" e "Some_other_also_very_long_input_name", respectivamente, na seção de configuração do leitor.
IDs de sequência
Como já mencionado, cada linha separada no arquivo de entrada representa uma sequência que contém um único exemplo para cada entrada. No entanto, se uma linha for prefixada com um número não negativo, o número será usado como a ID de sequência correspondente. Todas as linhas subsequentes que compartilham a mesma ID de sequência são mescladas para se tornarem parte da mesma sequência. Portanto, repetir o mesmo prefixo numérico para linhas N permite criar uma sequência de várias amostras, com cada entrada contendo entre 1 e N amostras. Omitir o prefixo de sequência na segunda e nas linhas a seguir tem o mesmo efeito. Assim, o conjunto de dados de exemplo acima define cinco sequências com ids100
, 333
200
400
e .500
Definir skipSequenceIds
o parâmetro na seção de leitor para true
, força o leitor a ignorar todas as IDs de sequência explícitas no conjunto de dados e tratar linhas separadas como sequências individuais. Além disso, omitir a ID da sequência na primeira linha do conjunto de dados tem o mesmo efeito : todas as IDs de sequência subsequentes são ignoradas, linhas tratadas como sequências individuais, como neste exemplo:
|a 1 2 3 |b 100 200
100 |a 4 5 6 |b 101 201
200 |b 102983 14532 |a 7 8 9
Algumas coisas finais a serem consideradas ao usar sequências:
- As IDs de sequência devem ser exclusivas.
- Os prefixos de ID só podem ser repetidos para linhas consecutivas.
- O comprimento da sequência em linhas (ou seja, o número de linhas que compartilham o mesmo prefixo de ID) não deve exceder o comprimento máximo de entrada em amostras (o número de amostras em uma entrada) nesta sequência.
Por exemplo, os seguintes conjuntos de dados são inválidos:
100 |a 1 2 3 |b 100 200
200 |a 4 5 6 |b 101 201
100 |b 102983 14532 |a 7 8 9
123 |a 1 2 3 |b 100 200
456 |a 4 5 6
456 |b 101 201
Alguns exemplos de Real-World
- Classificação: cada linha contém um exemplo, que consiste em um rótulo e recursos. Nenhuma ID de sequência é necessária, pois cada linha é sua própria "sequência" de comprimento 1.
|class 23:1 |features 2 3 4 5 6
|class 13:1 |features 1 2 0 2 3
...
- DSSM: cada linha contém um par de documentos de destino de origem, expressos por meio de um recipiente de palavras, codificados como vetores esparsos.
|src 12:1 23:1 345:2 45001:1 |tgt 233:1 766:2 234:1
|src 123:1 56:1 10324:1 18001:3 |tgt 233:1 2344:2 8889:1 2234:1 253434:1
- Marcação de parte da fala: sequências mapeando cada elemento para um rótulo correspondente. As sequências são alinhadas verticalmente (uma palavra + marca por linha).
0 |word 234:1 |tag 12:1
0 |word 123:1 |tag 10:1
0 |word 123:1 |tag 13:1
1 |word 234:1 |tag 12:1
1 |word 123:1 |tag 10:1
...
- Classificação de sequência: sequências mapeadas para um único rótulo. As sequências são alinhadas verticalmente; O rótulo "class" pode ocorrer em qualquer linha que tenha a mesma sequenceId.
Observação
No momento, o número de linhas não deve exceder o comprimento da sequência mais longa. Isso significa que o rótulo não pode aparecer em uma linha por conta própria. Esse é um detalhe de implementação que será levantado no futuro.
0 |word 234:1 |class 3:1
0 |word 123:1
0 |word 890:1
1 |word 11:1 |class 2:1
1 |word 344:1
- Sequência para sequência: mapeie uma sequência de origem para uma sequência de destino. As duas sequências são alinhadas verticalmente e, no caso mais fácil, apenas impressas após outra. Eles são unidos por terem a mesma "ID de sequência" geral (que, em seguida, se torna uma "ID da unidade de trabalho" nesse caso).
Observação
No momento, o número de linhas não deve exceder o comprimento da sequência mais longa. Isso significa que as sequências devem ser alinhadas horizontalmente. Esse é um detalhe de implementação que será levantado no futuro.
0 |sourceWord 234:1 |targetWord 344:1
0 |sourceWord 123:1 |targetWord 456:1
0 |sourceWord 123:1 |targetWord 2222:1
0 |sourceWord 11:1
1 |sourceWord 123:1
...
- Learning para Classificar: uma "sequência" representa uma consulta, cada exemplo de um documento com uma classificação rotulada à mão. Nesse caso, a "sequência" é apenas um multiconjunto que (no contexto de uma função de perda de aprendizado para classificação) não tem uma ordenação.
0 |rating 4 |features 23 35 0 0 0 21 2345 0 0 0 0 0
0 |rating 2 |features 0 123 0 22 44 44 290 22 22 22 33 0
0 |rating 1 |features 0 0 0 0 0 0 1 0 0 0 0 0
1 |rating 1 |features 34 56 0 0 0 45 1312 0 0 0 0 0
1 |rating 0 |features 45 45 0 0 0 12 335 0 0 0 0 0
2 |rating 0 |features 0 0 0 0 0 0 22 0 0 0 0 0
...
Parâmetros de configuração
Parâmetro | Descrição |
---|---|
precision |
Especifica a precisão do ponto flutuante (double ou float ) dos valores de entrada. Opcional, o padrão é float . |
reader
Seção
Parâmetro | Descrição |
---|---|
readerType |
Especifica um dos leitores de CNTK com suporte para carregar (por exemplo, CNTKTextFormatReader ). Obrigatório. |
file |
Caminho para o arquivo que contém o conjunto de dados de entrada (estilo Windows ou Linux). Obrigatório. |
randomize |
Especifica se a entrada deve ser aleatória (true , false ). Opcional, o padrão é true . |
randomizationSeed |
Valor de semente de randomização inicial (incrementado a cada varredura quando os dados de entrada são realeamensionados). Opcional, o padrão é 0 . |
randomizationWindow |
Especifica o tamanho (inteiro positivo) da janela de randomização (ou seja, intervalo de randomização). Esse parâmetro afeta quanto do conjunto de dados precisa residir na memória ao mesmo tempo. Opcional, dependendo do sampleBasedRandomizationWindow valor, o padrão é o tamanho de todo o conjunto de dados em exemplos (ou seja, a entrada é aleatória em todo o conjunto de dados) ou 4 GB de espaço em disco em partes (ou seja, 128 quando o tamanho da parte é igual a 32 MB). Esse parâmetro é ignorado quando randomize é false . |
sampleBasedRandomizationWindow |
Se true , o tamanho da janela de randomização é interpretado como um determinado número de amostras, caso contrário , como um número de partes. Opcional, o padrão é false . Da mesma forma que randomizationWindow , esse parâmetro é ignorado, quando randomize é false . |
skipSequenceIds |
Se true , o leitor ignorará as IDs de sequência no arquivo de entrada, interpretando cada linha separada como uma sequência independente do tamanho 1 (consulte a seção nas IDs da sequência). Opcional, o padrão é false . |
maxErrors |
Número de erros de entrada após os quais uma exceção deve ser gerada. Opcional, o padrão 0 é , o que significa que o primeiro valor malformado disparará uma exceção. |
traceLevel |
Nível de verbosidade de saída. 0 - mostrar somente erros; 1 - mostrar erros e avisos; 2 - mostrar toda a saída. Opcional, o padrão é 1 . |
chunkSizeInBytes |
Número de bytes consecutivos a serem lidos do disco em uma única operação de leitura. Opcional, o padrão é 33554432 (32 MB). |
keepDataInMemory |
Se true , todo o conjunto de dados será armazenado em cache na memória. Opcional, o padrão é false . |
frameMode |
true sinaliza o leitor para usar um método de empacotamento otimizado para quadros (sequências que contêm apenas um único exemplo). Opcional, o padrão é false . |
cacheIndex |
Especifica se os metadados criados durante a fase de pré-processamento devem ser gravados no disco e carregados no disco, se disponíveis (true , false ). Opcional, o padrão é false . Para obter mais detalhes, consulte a seção abaixo. Novidades no CNTK versão 2.1. |
Cache de índice
Observação
Novidades no CNTK versão 2.1.
O cache de índice permite reduzir significativamente (por um fator de 2-3x) os tempos de inicialização, especialmente ao trabalhar com arquivos de entrada grandes. Definir o cacheIndex
sinalizador para true
sinalizar o leitor para gravar os metadados de indexação no disco (mesmo diretório que o arquivo de entrada) se o arquivo de cache não estiver disponível ou se ele estiver obsoleto (mais antigo que o arquivo de entrada). A gravação é o melhor esforço e é executada em um thread separado para não afetar o desempenho do leitor. Se o arquivo de cache estiver presente e estiver atualizado, o leitor não usará mais o arquivo de entrada para compilar o índice. Em vez disso, ele carregará o índice do arquivo de cache. Observe que determinados parâmetros de configuração de leitor têm um impacto direto na indexação (por exemplo, valores frameMode
diferentes podem resultar em índices que têm um número diferente de sequências). Por esse motivo, um arquivo de cache pode ser ignorado por um leitor com uma configuração diferente daquela que produziu o cache. Para ver o benefício completo do cache, a configuração não deve ser modificada em execuções subsequentes.
input
sub-seção
input
combina uma série de entradas individuais, cada uma com uma sub-seção de configuração apropriadamente rotulada. Todos os parâmetros descritos abaixo são específicos para uma sub-seção de nome de entrada associada a uma entrada específica.
Parâmetro | Descrição |
---|---|
alias |
Um nome de abreviação alternativo (cadeia de caracteres) usado para identificar a entrada no conjunto de dados. Opcional |
format |
Especifica o tipo de entrada (dense , sparse ). Obrigatório. |
dim |
Dimensão (inteiro positivo) do valor de entrada (ou seja, o número de valores de entrada em um exemplo de entrada densa , o limite superior no intervalo de índice para entrada esparsa ). Obrigatório. |
definesMBSize |
Sinalizador (falso padrão), indicando se o tamanho da minibatch deve ser contado em exemplos desse fluxo específico Opcional. |
Você encontrará definições de rede completas e os exemplos de conjunto de dados correspondentes no repositório CNTK. Lá, você também encontrará um teste de ponta a ponta que usa o leitor CNTKTextFormat.