Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
(Observação: versões mais antigas do CNTK usaram "MEL" (Linguagem de Edição de Modelo) para estas finalidades. Ainda estamos no processo de converter os exemplos. Para obter a documentação sobre MEL, consulte o aqui.)
O CNTK permite que os modelos sejam editados após o fato. Isso é feito criando um novo modelo durante a clonagem (partes de) um modelo existente com modificações aplicadas. Para isso, o CNTK fornece três funções básicas:
-
BS.Network.Load()carregar um modelo existente -
BS.Network.CloneFunction()extrair uma seção de um modelo existente para reutilização -
BS.Network.Edit()clonar um modelo com modificações de nó por nó aplicadas
A operação de edição não é uma etapa separada. Em vez disso, um comando que deve funcionar fora de um modelo modificado não especificaria um modelPath para carregar o modelo, mas sim uma seção BrainScriptNetworkBuilder que carrega o modelo dentro e constrói um novo modelo do carregado em tempo real.
Exemplo: pré-treinamento discriminativo
O pré-treinamento discriminativo é uma técnica em que uma rede profunda é criada treinando uma sequência de redes mais rasas. Comece com uma rede de camada oculta 1, treine para convergência parcial, remova a camada de saída, adicione uma nova camada oculta e adicione uma nova camada de saída. Repita até que o número desejado de camadas ocultas seja atingido.
Vamos supor com um modelo inicial muito simples
BrainScriptNetworkBuilder = [
N = 40; M = 9000; H = 512
W1 = Parameter (H, N); b1 = Parameter (H)
Wout = Parameter (M, H); bout = Parameter (M)
x = Input (N, tag=‘feature’) ; labels = Input (M, tag=‘labels’)
h1 = Sigmoid (W1 * x + b1)
z = Wout * h1 + bout
ce = CrossEntropyWithSoftmax (labels, z, tag=‘criterion’)
]
Vamos treinar esse modelo e salvar em "model.1.dnn". Em seguida, queremos treinar um modelo com duas camadas ocultas, em que a primeira camada oculta é inicializada dos valores treinados acima. Para fazer isso, criamos uma ação de treinamento separada que cria um novo modelo, mas reutilizando partes da anterior, da seguinte maneira:
BrainScriptNetworkBuilder = {
# STEP 1: load 1-hidden-layer model
inModel = BS.Network.Load ("model.1.dnn")
# get its h1 variable --and also recover its dimension
h1 = inModel.h1
H = h1.dim
# also recover the number of output classes
M = inModel.z.dim
# STEP 2: create the rest of the extended network as usual
W2 = Parameter (H, H); b2 = Parameter (H)
Wout = Parameter (M, H); bout = Parameter (M)
h2 = Sigmoid (W2 * h1 + b2)
z = Wout * h2 + bout
ce = CrossEntropyWithSoftmax (labels, z, tag=‘criterion’)
}
Primeiro, a ETAPA 1 usa Load() para carregar a rede em uma variável BrainScript. A rede se comporta como um registro BrainScript, em que todos os nós de nível superior (todos os nós que não contêm um . ou [ em seus nomes de nó) são acessíveis por meio da sintaxe do registro. Uma nova rede pode referenciar qualquer nó em uma rede carregada. Neste exemplo, a rede carregada contém um nó h1 que é a saída da primeira camada oculta e um nó z que é a probabilidade posterior de log nãomalizada das classes de saída (entrada para a função Softmax). Ambos os nós podem ser acessados do BrainScript por meio da sintaxe de ponto, por exemplo, inModel.h1 e inModel.z.
Observe que as constantes não são armazenadas em modelos, portanto, nem N nem M estão disponíveis no modelo. No entanto, é possível reconstruí-los do modelo carregado. Para essa finalidade, os nós de computação também se comportam como registros BrainScript e expõem uma propriedade dim.
Em seguida, a ETAPA 2 constrói o restante da nova rede usando o BrainScript regular. Observe que esta nova seção simplesmente usa o nó h1 do modelo de entrada como uma entrada, como se ele usaria qualquer outro nó. Fazer referência a um nó da rede de entrada fará automaticamente todos os nós dos quais esse nó depende também de parte da rede recém-criada. Por exemplo, o nó de entrada x se tornará automaticamente parte da nova rede.
Observe também que a camada de saída é construída novamente. Dessa forma, seus parâmetros de modelo serão criados recentemente. (Para não fazer isso e reutilizar os parâmetros existentes, é possível usar inModel.Wout, mas observe que isso não faz sentido do ponto de vista de design de rede neste exemplo específico.)
Exemplo: usando um modelo pré-treinado
Veja a seguir um exemplo de como usar um modelo pré-treinado (de "./featext.dnn"de arquivo) como extrator de recursos:
BrainScriptNetworkBuilder = {
# STEP 1: load existing model
featExtNetwork = BS.Network.Load ("./featext.dnn")
# STEP 2: extract a read-only section that is the feature extractor function
featExt = BS.Network.CloneFunction (
featExtNetwork.input, # input node that AE model read data from
featExtNetwork.feat, # output node in AE model that holds the desired features
parameters="constant") # says to freeze that part of the network
# STEP 3: define the part of your network that uses the feature extractor
# from the loaded model, which above we isolated into featExt().
# featExt() can be used like any old BrainScript function.
input = Input (...)
features = featExt (input) # this will instantiate a clone of the above network
# STEP 4: and add the remaining bits of the network in BrainScript, e.g.
h = Sigmoid (W_hid * features + b_hid) # whatever your hidden layer looks like
z = W_out * h + b_out
ce = CrossEntropyWithSoftmax (labels, z)
criterionNodes = (ce)
}
A ETAPA 1 usa Load() para carregar a rede em uma variável BrainScript.
A ETAPA 2 usa CloneFunction() para clonar a seção relacionada à extração de recursos da rede carregada, que é o sub-grafo que conecta featExtNetwork.input a featExtNetwork.feat. Como especificamos parameters="constant", todos os parâmetros dos quais featExtNetwork.feat dependem também são clonados e feitos somente leitura.
Na ETAPA 3 e 4, a nova rede é definida. Isso é feito como qualquer outro modelo do BrainScript, apenas que agora podemos usar a função featExt() ao fazer isso.
Problemas com nomes de nó com .[ e ]
Para fazer referência a um nó em uma rede que contém . ou [ ou ], substitua esses caracteres por _.
Por exemplo, se network contiver um nó chamado result.z, network.result.z falhará; em vez disso, diga network.result_z.
Exemplo: modificando nós de uma rede existente
Para modificar partes internas de uma rede existente, seria realmente clonar a rede, enquanto as modificações são aplicadas como parte do processo de clonagem. Isso é feito por BS.Network.Edit().
Edit() iterará em todos os nós de uma rede e oferecerá cada nó, um por um, para funções lambda passadas pelo chamador. Essas funções lambda podem inspecionar o nó e retornar o nó sem modificação ou retornar um novo nó em seu lugar.
Edit() iterará em nós em ordem não especificada. Se um nó de substituição fizer referência a um nó de rede que, por sua vez, foi substituído, Edit() atualizará todas essas referências para as respectivas substituições (também conhecidas como "fazer a coisa certa").
TODO: Exemplo.