Leitor de formato de CNTK de texto brainScript
Esta página documenta o CNTKTextFormatReader do ponto de vista do BrainScript, mas Python utilizadores podem aprender lendo este documento também -- os conceitos, parâmetros e padrões são todos iguais.
CNTKTextFormatReader (mais tarde simplesmente LEITOR CTF) foi concebido para consumir dados de texto de entrada formatados de acordo com a especificação abaixo. Suporta as seguintes características principais:
- Múltiplos fluxos de entrada (entradas) por ficheiro
- Entradas escassas e densas
- Sequências de comprimento variável
formato de texto CNTK (CTF)
Cada linha no ficheiro de entrada contém uma amostra para uma ou mais entradas. Uma vez que (explicitamente ou implicitamente) cada linha também está ligada a uma sequência, define uma ou mais <sequências, entradas, relações de amostra> . Cada linha de entrada deve ser formatada da seguinte forma:
[Sequence_Id](Sample or Comment)+
em que
Sample=|Input_Name (Value )*
Comment=|# some content
- Cada linha começa com um id de sequência e contém uma ou mais amostras (por outras palavras, cada linha é uma recolha não ordenado de amostras).
- O id da sequência é um número. Pode ser omitido, caso em que o número da linha será usado como id de sequência.
- Cada amostra é efetivamente um par de valor-chave composto por 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 amostra começa com um símbolo de tubo (
|
) seguido pelo nome de entrada (sem espaços), seguido por um delimitador de espaço branco e, em seguida, uma lista de valores. - Cada valor é um número ou um número pré-fixado de índice para entradas escassas.
- Tanto os separadores como os espaços podem ser utilizados alternadamente como delimiters.
- Um comentário começa com um tubo imediatamente seguido por um símbolo de haxixe:
|#
, em seguida, seguido pelo conteúdo (corpo) do comentário. O corpo pode conter quaisquer caracteres, no entanto um símbolo de tubo dentro do corpo precisa de ser escapado colocando o símbolo de haxixe nele (ver exemplo abaixo). O corpo de um comentário continua até ao fim da linha ou o próximo cano não escapado, o que vier primeiro.
Exemplo simples
Este exemplo baseia-se num conjunto mínimo de parâmetros e opções de formato.
Para utilizar o leitor CTF, coloque a CNTKTextFormatReader
definição readerType
na secção de leitor da sua configuração 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 ...
(Este fragmento, bem como outros exemplos NDL neste documento apresentam apenas reader
secção, omitindo o resto da configuração CNTK; ver o final desta página para ponteiros para um conjunto de exemplo completo Redes e os conjuntos de dados correspondentes)
O leitor CTF requer o seguinte conjunto de parâmetros:
file
- caminho para o ficheiro com o conjunto de dados.input
- sub-secção que define as entradas identificadas pelos nomes de entrada (A
B
eC
no exemplo acima). Dentro de cada entrada devem ser especificados os seguintes parâmetros necessários:format
- especifica o tipo de entrada. Deve serdense
ousparse
dim
- especifica a dimensão do vetor de valor de entrada (para entrada densa isto corresponde diretamente ao número de valores em cada amostra , pois este representa o limite superior na gama de possíveis valores de índice).
Os dados de entrada correspondentes à configuração do leitor acima devem ser semelhantes:
|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
Note o seguinte sobre o formato de entrada:
|Input_Name
identifica o início de cada amostra de entrada. Este elemento é obrigatório e é seguido pelo vetor de valor correspondente.- Vetor denso é apenas uma lista de valores de pontos flutuantes; vetor escasso é uma lista de
index:value
tuples. - Tanto os separadores como os espaços são permitidos como delimiters de valor (dentro dos vetores de entrada) bem como os delimiters 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 alargado abaixo).
- Cada identificador de entrada só pode aparecer uma vez numa única linha (o que se traduz numa amostra por entrada por requisito de linha).
- A ordem das amostras de entrada dentro de uma linha NÃO é importante (conceptualmente, cada linha é uma coleção não ordenada de pares de valores-chave)
- Cada linha bem formada deve terminar com os símbolos "Line Feed"
\n
ou "Carriage Return, Line Feed\r\n
".
Exemplo alargado
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 utilizados 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 composto, 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 ficheiro de entrada correspondente pode então olhar aproximadamente da seguinte forma:
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 duas características adicionais:
Pseudónimos de nome de entrada
Os nomes de entrada podem ser arbitrários longos e, assim, repeti-los em todo o ficheiro de entrada pode não ser eficiente em termos de espaço. Para mitigar isto, o conjunto de dados pode usar "pseudónimos" em vez de nomes de entrada completos. Os pseudónimos devem então ser especificados dentro de cada subsecção de entrada. No nosso exemplo, o conjunto de dados utiliza pseudónimos a
e b
, que são mapeados para "Some_very_long_input_name" e "Some_other_also_very_long_input_name" respectivamente na secção de config do leitor.
IDs de sequência
Como já foi mencionado, cada linha separada no ficheiro de entrada representa uma sequência contendo uma única amostra para cada entrada. No entanto, se uma linha for pré-fixa com um número não negativo, o número é usado como id de sequência correspondente. Todas as linhas subsequentes que partilham o mesmo id de sequência são fundidas para se tornarem parte da mesma sequência. Portanto, repetir o mesmo prefixo numérico para linhas N permite acumular uma sequência de múltiplas amostras, com cada entrada contendo entre 1 e N amostras. Omitir o prefixo da sequência na segunda e seguinte linhas tem o mesmo efeito. Assim, o conjunto de dados de exemplo acima define cinco sequências com ids 100
, 200
, 333
e 400
500
.
Definir skipSequenceIds
o parâmetro na secção do leitor para true
, força o leitor a ignorar todos os ids de sequência explícita no conjunto de dados e a tratar linhas separadas como sequências individuais. Além disso, omitir a sequência id na primeira linha no conjunto de dados tem o mesmo efeito -- todos os ids de sequência subsequente são ignorados, 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 ter em conta ao utilizar sequências:
- Os ids de sequência devem ser únicos.
- Os prefixos de identificação só podem ser repetidos por linhas consecutivas.
- O comprimento da sequência em linhas (ou seja, o número de linhas que partilham o mesmo prefixo de id) não deve exceder o comprimento máximo de entrada em amostras (o número de amostras numa 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 Real-World
- Classificação: Cada linha contém uma amostra, composta por um rótulo e características. Não é necessária nenhuma identificação de sequência, uma vez que cada linha é a 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 origem-alvo, expresso através de um saco de palavras, codificado como vetores escassos.
|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 do discurso: Sequências mapeando cada elemento para uma etiqueta correspondente. As sequências estão alinhadas verticalmente (uma palavra + etiqueta 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 da sequência: Sequências mapeadas numa única etiqueta. As sequências estão alinhadas verticalmente; A etiqueta "classe" pode ocorrer em qualquer linha que tenha a mesma sequênciaId.
Nota
No momento, o número de linhas não deve exceder o comprimento da sequência mais longa. Isto significa que o rótulo não pode aparecer numa linha por si só. Trata-se de um pormenor 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: Mapear uma sequência de origem para uma sequência de alvo. As duas sequências estão alinhadas verticalmente e, no caso mais fácil, apenas impressas após outra. Juntam-se-lhes o mesmo "ID de sequência" geral (que, neste caso, se torna um "ID da unidade de trabalho").
Nota
No momento, o número de linhas não deve exceder o comprimento da sequência mais longa. Isto significa que as sequências devem ser alinhadas horizontalmente. Trata-se de um pormenor 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
...
- Aprendizagem a Rank: Uma "sequência" representa uma consulta, cada amostra de um documento com uma classificação etiquetada à mão. Neste caso, a "sequência" é apenas um multiconjunto que (no contexto de uma função de perda de aprendizagem para classificar) não tem uma encomenda.
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 | Description |
---|---|
precision |
Especifica a precisão do ponto flutuante (double ou float ) dos valores de entrada. Opcional, predefinições a float . |
reader
secção
Parâmetro | Description |
---|---|
readerType |
Especifica um dos leitores CNTK suportados para carregar (por exemplo, CNTKTextFormatReader ). É necessário. |
file |
Caminho para o ficheiro que contém o conjunto de dados de entrada (Windows ou estilo Linux). É necessário. |
randomize |
Especifica se a entrada deve ser aleatória (true , false ). Opcional, predefinições a true . |
randomizationSeed |
Valor inicial de sementes de aleatoriedade (incrementado cada varredura quando os dados de entrada são re-aleatórios). Opcional, predefinições a 0 . |
randomizationWindow |
Especifica o tamanho (inteiro positivo) da janela de aleatoriedade (isto é, intervalo de aleatoriedade). Este parâmetro afeta a quantidade de conjunto de dados que precisa de residir na memória de uma só vez. Opcional, dependendo do sampleBasedRandomizationWindow valor, predefini tanto quanto o tamanho de todo o conjunto de dados em amostras (ou seja, a entrada é aleatória em todo o conjunto de dados), ou 4GB de espaço de disco no valor de pedaços (ou seja, 128 quando o tamanho do pedaço é igual a 32MB). Este parâmetro é ignorado quando randomize é false . |
sampleBasedRandomizationWindow |
Se true , o tamanho da janela de aleatoriedade for interpretado como um certo número de amostras, caso contrário, como uma série de pedaços. Opcional, predefinições a false . Da mesma forma randomizationWindow , este parâmetro é ignorado, quando randomize é false . |
skipSequenceIds |
Se true , o leitor ignorar os IDs de sequência no ficheiro de entrada, interpretando cada linha separada como uma sequência independente do tamanho 1 (ver a secção nos ids de sequência). Opcional, predefinições a false . |
maxErrors |
Número de erros de entrada após os quais deve ser levantada uma exceção. Opcional, o incumprimento de 0 , o que significa que o primeiro valor mal formado irá desencadear uma exceção. |
traceLevel |
Nível de verbosidade de saída. 0 - mostrar apenas erros; 1 - apresentar erros e advertências; 2 - mostrar toda a produção. Opcional, predefinições a 1 . |
chunkSizeInBytes |
Número de bytes consecutivos para ler a partir de disco numa única operação de leitura. Opcional, predefinições para 33554432 (32MB). |
keepDataInMemory |
Se true , todo o conjunto de dados for colocado em cache na memória. Opcional, predefinições a false . |
frameMode |
true sinaliza o leitor para usar um método de embalagem otimizado para quadros (sequências que contêm apenas uma amostra). Opcional, predefinições a false . |
cacheIndex |
Especifica se os meta-dados construídos durante a fase de pré-processamento devem ser escritos para o disco e carregados a partir do disco se disponível (true , false ). Opcional, predefinições a false . Para mais detalhes, consulte a secção abaixo. Novo na versão 2.1 CNTK. |
Caching de índice
Nota
Novo na versão 2.1 CNTK.
O caching do índice permite reduzir significativamente (por um fator de 2-3x) tempos de arranque, especialmente quando se trabalha com grandes ficheiros de entrada. A definição da cacheIndex
bandeira true
irá sinalizar o leitor para escrever os meta-dados de indexação ao disco (o mesmo diretório que o ficheiro de entrada) se o ficheiro cache não estiver disponível ou se estiver estagnado (mais antigo que o ficheiro de entrada). A escrita é o melhor esforço e é realizada num fio separado para não afetar o desempenho do leitor. Se o ficheiro cache estiver presente e estiver atualizado, o leitor deixará de desviar o ficheiro de entrada para construir o índice, em vez disso carregará o índice a partir do ficheiro cache. Por favor, note que certos parâmetros de configuração do leitor têm um impacto direto na indexação (por exemplo, diferentes valores podem frameMode
potencialmente resultar em índices que têm um número diferente de sequências). Por essa razão, um ficheiro cache poderia ser ignorado por um leitor com uma configuração diferente daquela que produzia a cache. Para ver o benefício total do caching, a configuração não deve ser modificada em repetições subsequentes.
input
sub-secção
input
combina uma série de entradas individuais, cada uma com uma subesposição de configuração devidamente rotulada. Todos os parâmetros descritos abaixo são específicos de uma sub-secção de nome de entrada associada a uma determinada entrada.
Parâmetro | Description |
---|---|
alias |
Um nome de abreviatura alternativa (cadeia) usado para identificar a entrada no conjunto de dados. Opcional |
format |
Especifica o tipo de entrada (dense , sparse ). É necessário. |
dim |
Dimensão (número de entradas de dados positivos) do valor de entrada (isto é, o número de valores de entrada numa amostra para entrada densa , o limite superior na gama de índices para uma entrada escassa ). É necessário. |
definesMBSize |
Bandeira (falso predefinido), indicando se o tamanho da minibatch deve ser contado em amostras deste fluxo particular Opcional. |
Encontrará definições de rede completas e os exemplos de dados correspondentes no Repositório CNTK. Lá, também encontrará um teste de ponta a ponta que utiliza o leitor CNTKTextFormat.