Como devo proceder para modelos de comboio no BrainScript
- Realizar treino em camadas?
- Treinar com um objetivo multitask?
- Treinar um modelo de regressão nas imagens?
- Treinar um classificador multilabel?
- Começar em sequência para modelação de sequências?
- Treine um modelo DSSM (ou um modelo convolucional-DSSM) ?
- Treine um codificador de imagem com desconvolução e descoamento?
- Deteção de objetos usando R-CNN rápido?
Treino sábio em camadas
Para realizar treino em camadas basta utilizar vários "comandos" no seu ficheiro config, onde cada comando é de tipo action=train.
command = TrainLayer1:TrainLayer2:TrainLayer3:EndToEndTrain:Test:Output
TrainLayer1= [
action = train
...
]
TrainLayer2= [
action = train
...
]
...
Treine com um objetivo multitask
Pode definir o seu critério combinado como uma expressão BrainScript e pode monitorizar todas as perdas de tarefas individuais especificando-as como evaluationNodes
.
task1loss = CrossEntropyWithSoftMax(prediction,label)
task2loss = SquareError(reconstruction,input)
mtloss = task1loss + Constant(0.3) .* task2loss
criterionNodes = (mtloss)
evaluationNodes = (task1loss:task2loss)
Treine um modelo de regressão em imagens
Abaixo descrevemos como prever um ou mais valor de ponto flutuante para uma imagem de entrada usando CNTK. Um exemplo de caso de uso é prever uma caixa de delimitação, por exemplo como (x, y, w, h), de um objeto em uma determinada imagem. Também se pode pensar em prever o preço de um carro só de olhar para uma imagem daquele carro (seria interessante na verdade). Aqui usamos um exemplo muito simples em que treinamos uma rede para prever os valores médios de RGB de uma imagem (normalizada para [0, 1]). No entanto, os mesmos passos aplicam-se a outros casos de utilização. Estes passos são:
- Defina tanto a imagem como os rótulos de regressão da verdade no solo como entradas para a sua rede
- Defina uma rede que prevê um número de valores correspondentes w.r.t. as suas etiquetas de regressão
- Definir uma função de perda que compara os valores previstos com a verdade do solo
- Adapte a secção de leitor no seu ficheiro .cntk config para ler as etiquetas de imagem e regressão
Eis como pôde fazê-lo. O ficheiro config completo está incluído na pasta Exemplos /Imagem/Regressão/RegrSimple_CIFAR10.cntk. Esta pasta também contém os scripts para descarregar os dados de imagem e gerar a verdade de regressão para treino e teste.
1-3) Definição da função de entrada, rede e perda:
BrainScriptNetworkBuilder = [
imageShape = 32:32:3
featScale = Constant(1/256)
labelDim = 3
model (features) = {
featNorm = Scale(features, featScale)
h1 = LinearLayer {100, init="gaussian", initValueScale=1.5} (featNorm)
ol = LinearLayer {labelDim, init="gaussian", initValueScale=1.5} (h1)
}.ol
# inputs
features = Input {imageShape}
regrLabels = Input {labelDim}
# apply model to features
ol = model (features)
# define regression loss
# rmse = sqrt(SquareError(regrLabels, ol) / labelDim)
sqerr = SquareError (regrLabels, ol)
rmse = Sqrt (Constant(1/labelDim).* sqerr)
featureNodes = (features)
labelNodes = (regrLabels)
criterionNodes = (rmse)
evaluationNodes = (rmse)
OutputNodes = (ol)
]
- Definição de um leitor composto utilizando o ImageReader e o CNTKTextFormatReader:
reader = {
verbosity = 0 ; randomize = true
deserializers = ({
type = "ImageDeserializer" ; module = "ImageReader"
file = "$dataDir$/cifar-10-batches-py/train_map.txt"
input = {
features = { transforms = (
{ type = "Scale" ; width = 32 ; height = 32 ; channels = 3 ; interpolations = "linear" } :
{ type = "Transpose" }
)}
ignored = { labelDim = 10 }
}
} : {
type = "CNTKTextFormatDeserializer" ; module = "CNTKTextFormatReader"
file = "$dataDir$/cifar-10-batches-py/train_regrLabels.txt"
input = {
regrLabels = { dim = 3 ; format = "dense" }
}
})
}
O leitor é um leitor composto que usa o ImageReader para ler imagens e o CNTKTextFormatReader para ler as etiquetas de verdade terrestre de regressão. Fá-lo definindo um conjunto de deserializadores (utilizando {...} : {...}
) e atribuindo as entradas definidas na rede acima (cf. recursos e regrLabels).
Consulte exemplos/Imagem/Miscelânea/CIFAR-10/06_RegressionSimple.cntk para o ficheiro config completo e o Readme correspondente nessa pasta para executar o exemplo.
Treine um classificador multilabel
Para a classificação multilabel deve evitar usar CrossEntropy, uma vez que só pode manusear vetores de entrada que se resumem a 1. Uma alternativa sensata é usar uma soma de funções de perda logística, uma para cada saída
...
probabilities = DenseLayer {outputSize, activation=Sigmoid} (hidden)
logisticLoss = Logistic (multiLabels, probabilities)
trainingCriterion = (logisticLoss)
...
Para além da perda em si, é possível que queira monitorizar outras métricas, como o número de previsões incorretas. Não há expressão construída para isso, mas pode ser expressa como
...
hammingLoss (y, p) = ReduceSum (y != (p > 0.5))
hl = hammingLoss(multiLabels,probabilities)
evaluationNodes = (hl)
...
Isto conta o número de vezes que [i] discorda do p[i]>0.5.
Começar em sequência para modelação de sequência
Este laboratório prático descreve os principais ingredientes para começar o processamento de sequências, como o formato de texto CNTK e como configurar o leitor para usar pseudónimos curtos para as várias sequências de entrada. O exemplo grafeme-to-phoneme (G2P) demonstra uma tarefa de sequência-a-sequência real.
Uma questão importante para modelação de sequência-a-sequência é como descodificar dados de teste com pesquisa de feixes. Isto pode ser feito numa secção do seu config onde a ação de nível superior é "escrever". Descoding requer uma busca pela sequência mais provável de saídas. CNTK tem um descodificador de pesquisa de feixe enquanto você pode chamar assim
BrainScriptNetworkBuilder = (BS.Seq2Seq.BeamSearchSequenceDecoderFrom (
BS.Network.Load (decodeModelPath), beamSize))
e executará a procura do feixe com o tamanho do feixe especificado. Para um feixe tamanho de 1 há um descodificador ganancioso especializado
BrainScriptNetworkBuilder = (BS.Seq2Seq.GreedySequenceDecoderFrom (
BS.Network.Load (decodeModelPath)))
Ambos os descodificam requisitos específicos para a rede, como mostra o exemplo do G2P
Treine um modelo DSSM (ou um DSSM convolucional)
DSSM (ou Deep Semmantic Similarity Model) é um modelo DNN treinado em pares de textos-alvo de origem, para aprender um espaço de incorporação de texto curto onde os pares de texto relevantes de origem e alvo estão mais próximos. A entrada de texto no modelo é representada pelo seu haxixe trigrama pré-calculado (ver, Huang et al.). Para o C-DSSM, o haxixe trigrama é calculado por palavra e, em seguida, concatenado na ordem em que as palavras ocorrem no texto. A entrada para ambos os modelos é de tamanho fixo. Se considerarmos trigramas de 50K, então a entrada DSSM correspondente à fonte e o texto-alvo seria um vetor de comprimento de 50K cada. Para o C-DSSM, o vetor seria de comprimento 50K x n, onde os primeiros vetores de palavra n-1 são concatenados, e o vetor nº contém uma soma dos vetores correspondentes a todas as palavras restantes no texto. Se houver menos de n palavras no texto, então o resto do vetor é acolchoado com zeros. Para desenhar uma analogia com a imagem, pode pensar na entrada de texto para C-DSSM como uma imagem com dimensões 10x1 e 50K canais armazenados num [C x H x W]
formato.
Este exemplo demonstra como treinar um modelo DSSM /C-DSSM utilizando o CNTKTextFormatReader. Os dados devem conter 2 características (texto de origem e alvo) e 1 etiqueta (que é sempre definida para o valor 1 nos dados de formação, uma vez que contém apenas amostras positivas – durante a formação os exemplos-alvo negativos são gerados por amostragem aleatória). Aqui está a configuração do leitor,
reader = {
verbosity = 0
randomize = true
deserializers = ({
type = "CNTKTextFormatDeserializer"
module = "CNTKTextFormatReader"
file = "data.txt"
input = {
Q = { dim = 500000; format = "sparse" }
D = { dim = 500000; format = "sparse" }
L = { dim = 1; format = "dense" }
}
})
}
Uma amostra dos dados de entrada,
|L 1 |Q 482:1 761:1 1832:1 2117:1 12370:1 17131:1 17854:1 24976:1 27676:1 28055:1 28177:1 29507:1|D 482:1 761:1 1832:1 2117:1 12370:1 17131:1 17854:1 24976:1 27676:1 28055:1 28177:1 29507:1
|L 1 |Q 149:1 153:1 595:1 671:1 675:1 1110:1 1517:1 2077:1 2114:1 5533:1 5662:1 6886:1 6901:1 7294:1 12846:1 13033:1 16614:1 19425:1 22015:1 24839:1 24994:1 26196:1 26358:1 27565:1|D 149:1 153:1 595:1 671:1 675:1 1110:1 1517:1 2077:1 2114:1 5533:1 5662:1 6886:1 6901:1 7294:1 12846:1 13033:1 16614:1 19425:1 22015:1 24839:1 24994:1 26196:1 26358:1 27565:1
|L 1 |Q 187:1 2294:1 2800:1 6920:1|D 187:1 2294:1 2800:1 6920:1
E, finalmente, a definição de rede,
BrainScriptNetworkBuilder = {
# Constants scalars
isConvolutional = true
numWords = (if isConvolutional then 10 else 1)
numTrigramsPerWord = 50000
numHiddenNodes = 300
wordWindowSize = 3
numWindows = numWords - wordWindowSize + 1
numNeg = 50
# Constant tensors
CONST_GAMMA = Constant(10)
CONST_SHIFT = Constant(1)
CONST_NEG = Constant(numNeg)
CONST_PAD_NEG = Constant(0, rows=numNeg, cols=1)
CONST_PAD_POS = Constant(1, rows=1, cols=1)
CONST_PAD = Splice(CONST_PAD_POS : CONST_PAD_NEG, axis=1)
# Inputs
Q = Input(500000)
D = Input(500000)
L = Input(1)
qr = if isConvolutional
then TransposeDimensions(ReshapeDimension(Q, 1, numTrigramsPerWord:1:numWords), 1, 3)
else Slice(0, numTrigramsPerWord, Q, axis=1)
dr = if isConvolutional
then TransposeDimensions(ReshapeDimension(D, 1, numTrigramsPerWord:1:numWords), 1, 3)
else Slice(0, numTrigramsPerWord, D, axis=1)
qdssm = Sequential (
DenseLayer {numHiddenNodes, activation=Tanh} :
DenseLayer {numHiddenNodes, activation=Tanh} :
DenseLayer {numHiddenNodes, activation=Tanh})
qcdssm = Sequential (
ConvolutionalLayer {numHiddenNodes, (wordWindowSize:1), pad=false, activation=Tanh} :
MaxPoolingLayer {(numWindows:1), stride=(1:1)} :
DenseLayer {numHiddenNodes, activation=Tanh} :
DenseLayer {numHiddenNodes, activation=Tanh})
ddssm = Sequential (
DenseLayer {numHiddenNodes, activation=Tanh} :
DenseLayer {numHiddenNodes, activation=Tanh} :
DenseLayer {numHiddenNodes, activation=Tanh})
dcdssm = Sequential (
ConvolutionalLayer {numHiddenNodes, (wordWindowSize:1), pad=false, activation=Tanh} :
MaxPoolingLayer {(numWindows:1), stride=(1:1)} :
DenseLayer {numHiddenNodes, activation=Tanh} :
DenseLayer {numHiddenNodes, activation=Tanh})
qembed = if isConvolutional
then qcdssm
else qdssm
dembed = if isConvolutional
then dcdssm
else ddssm
qf = qembed(qr)
df = dembed(dr)
lf = Times(CONST_PAD, L)
c = CosDistanceWithNegativeSamples(qf, df, CONST_SHIFT, CONST_NEG)
s = Slice(0, 1, c, axis=1, tag="output")
ce = CrossEntropyWithSoftmax(lf, Scale(CONST_GAMMA, c), tag="criterion")
}
Nota:
- Embora o C-DSSM tenha demonstrado ter um desempenho consistentemente melhor do que o DSSM, também treina mais devagar (algum tempo até 5-10x mais lento). Assim, em alguns casos, poderá obter um melhor desempenho do DSSM no mesmo tempo de treino, treinando mais dados (ou para mais épocas).
- Os DSSM originais / C-DSSM foram treinados em pares de títulos de consulta e documento. Mas pode aprender outras relações entre textos curtos treinando sobre outros tipos de dados, tais como pares de consulta de sessão ou pares de prefixos de consulta.
Treine um codificador de imagem usando desconvolução e descopooling
Há instruções aqui.
Deteção de objetos de trem usando Fast R CNN
Há instruções aqui.