Partilhar via


BrainScript através de regras de análise de linha de comando

Abaixo descrevemos as regras de análise da linha de comando CNTK. CNTK consiste em vários componentes para completar uma tarefa. A maioria destes componentes necessita de algumas informações de configuração disponíveis para funcionar, e estes parâmetros de configuração são fornecidos através de ficheiros de configuração em CNTK.

Os ficheiros de configuração são coleções de pares de valor-nome. Os dados de configuração podem ser um dos seguintes tipos:

  • Simples: um único valor é atribuído ao parâmetro de configuração. Por exemplo, deviceId = "Auto".
  • Matriz: é atribuído um parâmetro de configuração um conjunto de valores que não precisam de ser de um tipo uniforme. : é o separador padrão para matrizes. O separador pode ser alterado, encerrando os valores da matriz na parênteses e colocando o novo carácter separador imediatamente após a parêntese aberta. O * personagem permite que um valor particular seja repetido várias vezes na matriz. Por exemplo, minibatchSize = 256:512:512:512:1024 é igual a minibatchSize = 256:512*3:1024.
  • Conjunto: conjuntos de parâmetros contêm conjuntos de parâmetros de configuração de qualquer tipo. Os parâmetros podem ser aninhados. O separador predefinido para conjuntos de parâmetros é ; se vários itens estiverem incluídos numa linha. Os separadores de linha também servem como separadores para itens. Por exemplo:

block1 = [id=1;size=256]

block2 = [
    subblock = [string="hi";num=5]
    value = 1e-10
    array = 10:"this is a test":1.25
]

Em CNTK, os ficheiros de configuração são organizados de forma hierárquica. Os valores reais dos dados não são avaliados até que um componente CNTK solicite o valor. Quando um valor é solicitado por um componente, CNTK procurará primeiro no interior do bloco de componentes. Se o valor não for encontrado, continuará a procurar no parâmetro dos pais e avós definido até que o parâmetro seja encontrado, ou o nível superior da hierarquia de configuração seja atingido sem correspondência. Isto permite a quota dos mesmos valores de parâmetros mais fácil em diferentes blocos. Tal como discutimos anteriormente, para executar CNTK precisa de especificar o ficheiro de configuração na linha de comando, uma vez cntk configFile=yourExp.cntk que este carregará o ficheiro de configuração solicitado e executará qualquer bloco de comando listado nos parâmetros de comando no ficheiro de configuração.

Comandos e Ações

Deve existir um parâmetro de comando de nível superior, que defina os comandos (separados com :) que serão executados no ficheiro de configuração. Cada comando refere um bloco de comando no ficheiro, que deve conter um parâmetro de ação que defina a operação que o bloco irá executar. Por exemplo, o seguinte comando executará o mnistTrain bloco, que executa a ação do comboio, seguido do mnistTest bloco, que avalia o modelo.

command = mnistTrain:mnistTest

mnistTrain = [
    action = "train"
    ...
]

mnistTest = [
    action = "eval"
    ...
]

Sobrecargas de configuração na linha de comando

É comum ter uma configuração que pode ser usada como uma configuração base, e modificar apenas alguns parâmetros para cada execução experimental. Isto pode ser feito de várias maneiras diferentes, uma das quais é sobrepor as definições na linha de comando. Por exemplo, para anular o caminho de ficheiro modelo, pode-se simplesmente modificar a linha de comando da seguinte forma:

cntk configFile=yourExp.cntk stderr="c:\temp\newpath"

Isto irá sobrepor-se à definição atual para stderr, que é definida ao nível da raiz do ficheiro de configuração, com o novo valor. Se um parâmetro dentro de um bloco de comando precisar de ser modificado, o bloco também precisa de ser especificado. Por exemplo, pode-se mudar o minibatchSize para uma experiência na linha de comando como

cntk configFile=yourExp.cntk mnistTrain=[minibatchSize=256]

ou modificar o ficheiro de dados utilizado para uma experiência como

cntk configFile=yourExp.cntk mnistTrain=[reader=[file="mynewfile.txt"]]

Ficheiros de configuração em camadas

Em vez de sobrepor algumas partes de um ficheiro de configuração usando parâmetros da linha de comando, também se pode especificar vários ficheiros de configuração, onde os últimos ficheiros substituem os anteriores. Isto permite que um utilizador tenha um ficheiro de configuração principal e, em seguida, especifique, num ficheiro de configuração separado, quais os parâmetros do mestre que gostariam de substituir para uma determinada execução de CNTK. Isto pode ser realizado especificando uma lista separada '+' de ficheiros de configuração, ou usando a configFile= etiqueta várias vezes. Os seguintes são equivalentes.

cntk configFile=yourExp1.cntk+yourExp2.cntk

cntk configFile=yourExp1.cntk configFile=yourExp2.cntk

Se yourExp2.cntk ao menos contiver a corda mnistTrain=[reader=[file=mynewfile.txt]], então ambos os comandos seriam equivalentes a:

cntk configFile=yourExp1.cntk mnistTrain=[reader=[file="mynewfile.txt"]]

Note que o valor de uma variável é sempre determinado pela última vez que é atribuído. Também é possível misturar parâmetros de linha de comando, e ficheiros de configuração em camadas, em combinações arbitrárias. Por exemplo,

cntk configFile=yourExp1.cntk+yourExp2.cntk var1=value configFile=yourExp3.cntk

processaria estes parâmetros de configuração na ordem em que aparecem na linha de comando e qualquer valor atribuído por último é o valor utilizado.

Além de ser capaz de especificar vários ficheiros de configuração na linha de comando, um utilizador pode incluir um ficheiro de configuração dentro de outro. Por exemplo, se a primeira linha de yourExp2.cntk foi

include=yourExp1.cntk

em seguida, simplesmente correr

cntk configFile=yourExp2.cntk

seria equivalente a correr

cntk configFile=yourExp1.cntk+yourExp2.cntk

onde neste último caso, yourExp2.cntk não contém a declaração incluída. Note que estas declarações podem aparecer em qualquer lugar dentro de um ficheiro de configuração; onde quer que a declaração inclua, é aí que o ficheiro de configuração especificado será incluído. Incluir um ficheiro de configuração é equivalente a colar o conteúdo desse ficheiro no local da declaração de incluem. Incluem declarações que são resolvidas de forma recorrente (utilizando uma primeira pesquisa de profundidade), o que significa que se yourExpA.cntk incluir yourExpB.cntk, e yourExpB.cntk inclui yourExpC.cntk, então a cadeia completa será resolvida, e yourExpC.cntk será efetivamente incluída em yourExpA.cntk. Se um ficheiro de configuração for incluído várias vezes (por exemplo, 'A' inclui 'B' e 'C', e 'B' também inclui 'C'), então só será efetivamente incluído na primeira vez que for encontrado.

Variáveis Stringize

Embora os ficheiros de configuração em camadas permitam aos utilizadores reutilizar ficheiros de configuração em experiências, este ainda pode ser um processo complicado. Para cada experiência, um utilizador pode ter de ultrapassar vários parâmetros, alguns dos quais podem ser longos caminhos de ficheiro (por exemplo, stderr, modelPath). file A funcionalidade "stringize" pode tornar este processo muito mais fácil. Permite que um utilizador especifique a configuração como o seguinte:

command = SpeechTrain
stderr = "$Root$\$RunName$.log"
speechTrain = [
    modelPath = "$Root$\$RunName$.cn"
    SGD = [
        reader = [
            features = [
                type = "real"
                dim = "$DataSet1_Dim$"
                file = "$DataSet1_Features$"
            ]
        ]
    ]
]

Aqui, Rootestão DataSet1_DimRunNameDataSet1_Features especificadas em outros lugares da configuração (num âmbito visível a partir do ponto em que são utilizadas). Ao interpretar este ficheiro de configuração, o parser substituiria todas as cadeias do formulário pela cadeiaVarValue, onde VarValue representa o valor da variável chamada VarName.$VarName$ O processo de resolução variável é recursivo; por exemplo, se A=$B$, B=$C$, e C=HelloWorld.txt, então A seria resolvido como "HelloWorld.txt". Certifique-se de que não existe um ciclo de referência no seu ficheiro de configuração. Caso contrário, o parser entrará em loop infinito neste momento.

Note que por ser equivalente para um utilizador especificar o valor de uma variável num ficheiro de configuração vs. na linha de comando, os valores para estas variáveis podem ser especificados em qualquer local. Lembre-se que o valor de uma variável é determinado pela última vez que é atribuído, quer isso esteja num ficheiro de configuração, quer na linha de comando. Assim, se Root for definido em config1.txt, mas ultrapassado na linha de comando, então o valor especificado na linha de comando seria o usado para resolver instâncias de $Root$ configFile1.txt. Uma característica útil é que se stderr ou modelPath apontar para diretórios que não existem, estes diretórios serão criados por CNTK; isto permite especificar algo como stderr = $Root$\$RunName$\$RunName$.log, mesmo que o diretório $Root$\$RunName$ não exista.

Predefinição, Valores Repetidos e Comentários

A maioria dos parâmetros em ficheiros de configuração têm um valor predefinido que será utilizado se não for especificado nenhum valor de configuração. Se não houver valor predefinido e o valor não puder ser encontrado numa pesquisa, será apresentada uma exceção e o programa sairá. Se um nome de parâmetro for especificado mais de uma vez, o último valor definido para esse valor é o que será mantido. A única exceção a isso é em conjuntos de parâmetros, que estão rodeados por [ aparelhos quadrados, nestes casos ]os valores dentro das chaves são considerados um parâmetro definido, e serão adicionados ao conjunto de parâmetros atualmente existente. Por exemplo:

params=[a=1;b=2;c=3]
params=[c=5;d=6;e=7]

é efetivamente igual a:

params=[a=1;b=2;c=5;d=6;e=7]

Note que este processamento de apêndice NÃO é utilizado para elementos de matriz, e toda a matriz será substituída se for definida várias vezes. O # personagem significa o início de um comentário, tudo o que ocorre após o # ser ignorado. O # deve ser precedido por whitespace ou estar no início da linha para ser interpretado como um comentário. A seguir, a reserva é uma nota válida.

stderr="c:\cntk\log\cntk" # "_mnistTrain_mnistTest.log"

Segue-se um exemplo de um valor que não será interpretado como um comentário. Define um parâmetro var para o infinito como o # in 1#INF não é um marcador de comentários

var=1#INF