Tvůrce sítě v jazyce BrainScript
Vlastní sítě jsou popsány v jazyce pro popis vlastní sítě cntk "BrainScript". Pokud chcete definovat vlastní síť, zahrňte do konfigurace trénování oddíl s názvem BrainScriptNetworkBuilder
. Podrobný popis jazyka popisu sítě najdete na stránce Základní koncepty a na odpovídajících dílčích stránkách.
Existují dvě formy použití tvůrce sítě BrainScript, jedna pomocí závorek (...)
a zkrácená forma používající složené závorky {...}
. Pokud chcete síť popsat v externím souboru, zadejte blok podobný tomuto:
BrainScriptNetworkBuilder = (new ComputationNetwork {
include "yourNetwork.bs"
})
kde yourNetwork.bs
obsahuje síť popsanou pomocí BrainScriptu. Soubor yourNetwork.bs
se nejprve hledá ve stejném adresáři jako konfigurační soubor, a pokud není nalezen, v adresáři spustitelného souboru CNTK. Tady se přijímají absolutní i relativní názvy cest. Například se rozumí soubor umístěný bs/yourNetwork.bs
v adresáři bs
vedle konfiguračního souboru (nebo případně adresář bs
uvnitř spustitelného adresáře CNTK).
Poznámka: Až do verze CNTK 1.6 používal BrainScript hranaté závorky [...]
místo složených závorek {...}
. Hranaté závorky jsou stále přijímány, ale jsou zastaralé.
Alternativně můžete definovat vloženou síť přímo v konfiguračním souboru. To může zjednodušit konfiguraci, pokud neplánujete sdílet stejný brain script napříč více konfiguracemi. Použijte tento formulář:
BrainScriptNetworkBuilder = {
# insert network description here
}
Jak vypadá kód BrainScriptu, který jde do hranatých závorek? Pokud to chcete zjistit, přejděte rovnou k části BrainScript Basic Concepts (Základní koncepty brainscriptu).
Nebo zůstaňte na této stránce a přečtěte si o některých méně často potřebných podrobnostech.
Výše {...}
uvedený formulář je ve skutečnosti jen zkratkou:
BrainScriptNetworkBuilder = (new ComputationNetwork {
# insert network description here
})
A konečně, jako rozšířené použití (...)
není formulář omezen na použití new
. Místo toho je každý výraz BrainScript, který se vyhodnotí jako objekt , ComputationNetwork
povolen uvnitř závorek. Příklad:
BrainScriptNetworkBuilder = ({
include "myNetworks.bs"
network = CreateMyNetworkOfType42()
}.network)
Jedná se o rozšířené použití, ke kterému také někdy dochází v kontextu úprav modelu.
Další: Základní koncepty brainscriptu.
Starší NDLNetworkBuilder
Ve starších verzích CNTK se tvůrce sítě jmenoval NDLNetworkBuilder
. Jazyk jeho definice je podmnožinou BrainScriptu. Starý analyzátor byl méně schopný, ale také více odpouštějící. Existují také další malé rozdíly.
NDLNetworkBuilder
je nyní zastaralá, ale vzhledem k podobnosti není obtížné upgradovat na BrainScriptNetworkBuilder
. Následuje průvodce převodem NDLNetworkBuilder
popisů sítě na BrainScriptNetworkBuilder
popisy sítě.
Aktualizace z NDLNetworkBuilder
na BrainScriptNetworkBuilder
Převod existující definice sítě pro NDLNetworkBuilder
na BrainScriptNetworkBuilder
je ve většině případů jednoduchý. Hlavní změny jsou syntaxe okolí. Samotný popis základní sítě je z velké části směrem nahoru kompatibilní a pravděpodobně identický nebo téměř identický, pokud nevyužíváte nové jazykové funkce.
Chcete-li převést popisy, musíte přepnout tvůrce sítě, přizpůsobit bez vnější syntaxe a případně provést menší úpravy samotného síťového kódu.
Krok 1. Přepnutí tvůrce sítě. NDLNetworkBuilder
Nahraďte odpovídajícím BrainScriptNetworkBuilder
blokem v konfiguračním souboru CNTK. Pokud je popis sítě v samostatném souboru:
# change from:
NDLNetworkBuilder = [
ndlMacros = "shared.ndl" # (if any)
networkDescription = "yourNetwork.ndl"
]
# ...to:
BrainScriptNetworkBuilder = (new ComputationNetwork {
include "shared.bs" # (if any)
include "yourNetwork.bs"
})
(Změna přípony názvu souboru není nezbytně nutná, ale doporučuje se.)
Pokud je popis sítě v samotném konfiguračním .cntk
souboru:
# change from:
NDLNetworkBuilder = [
# macros
load = [
SigmoidNetwork (x, W, b) = Sigmoid (Plus (Times (W, x), b))
]
# network description
run = [
feat = Input (13)
...
ce = CrossEntropyWithSoftmax (labels, z, tag="criterion")
]
]
# ...to:
BrainScriptNetworkBuilder = {
# macros are just defined inline
SigmoidNetwork (x, W, b) = Sigmoid (Plus (Times (W, x), b)) # or: Sigmoid (W * x + b)
# network description
feat = Input {13}
...
ce = CrossEntropyWithSoftmax (labels, z, tag="criterion")
}
Krok 2. Odebrat load
bloky a run
V nástroji BrainScriptNetworkBuilder
se kombinují definice maker a funkcí a hlavní kód. Bloky load
a run
je nutné jednoduše odebrat. Příklad:
load = ndlMnistMacros
run = DNN
ndlMnistMacros = [
featDim = 784
...
labels = InputValue(labelDim)
]
DNN = [
hiddenDim = 200
...
outputNodes = (ol)
]
jednoduše se stane:
featDim = 784
...
labels = InputValue(labelDim)
hiddenDim = 200
...
outputNodes = (ol)
Proměnnou jste mohli použít run
k výběru jedné z více konfigurací s externí proměnnou, například:
NDLNetworkBuilder = [
run = $whichModel$ # outside parameter selects model, must be either "model1" or "model2"
model1 = [ ... (MODEL 1 DEFINITION) ]
model2 = [ ... (MODEL 1 DEFINITION) ]
]
Tento model byl většinou nezbytný, protože NDL nemělo podmíněné výrazy. V BrainScriptu by to teď bylo napsané pomocí výrazu if
:
BrainScriptNetworkBuilder = (new ComputationNetwork
if "$whichModel$" == "model1" then { ... (MODEL 1 DEFINITION) }
else if "$whichModel$" == "model2" then { ... (MODEL 2 DEFINITION) }
else Fail ("Invalid model selector value '$whichModel$'")
)
Vybrané modely jsou si ale často velmi podobné, takže lepším způsobem by bylo sloučit jejich popisy a místo toho použít podmínky uvnitř pouze tam, kde se liší. Tady je příklad, kdy se parametr používá k výběru mezi jednosměrným a obousměrným LSTM:
encoderFunction =
if useBidirectionalEncoder
then BS.RNNs.RecurrentBirectionalLSTMPStack
else BS.RNNs.RecurrentLSTMPStack
encoder = encoderFunction (encoderDims, inputEmbedded, inputDim=inputEmbeddingDim)
Krok 3. Úprava popisu sítě. Pokud jde o samotný popis sítě (vzorce), je BrainScript s NDL kompatibilní z velké části směrem nahoru. Toto jsou hlavní rozdíly:
Návratová hodnota maker (funkcí) už není poslední proměnnou definovanou v nich, ale celou sadou proměnných. Výstupní hodnotu musíte explicitně vybrat na konci. Příklad:
# NDL: f(x) = [ x2 = Times (x, x) y = Plus (x2, Constant (1)) ] # <-- return value defaults to last entry, i.e. y # BrainScript: f(x) = { x2 = x*x y = x2 + 1 }.y # <-- return value y must be explicitly dereferenced
Bez této změny by návratovou hodnotou funkce byl celý záznam a typickou chybou
ComputationNode
, která se zobrazí, je, že byl očekáváno, kdeComputationNetwork
byl nalezen.BrainScript nepovoluje funkce s proměnnými čísly parametrů. To je důležité především pro
Parameter()
funkci: Parametr vektoru již nelze zapsat jakoParameter(N)
, musí být nyní explicitně zapsán jako tenzorParameterTensor{N}
nebo maticiParameter(N, 1)
o 1 sloupci . Bez této změny se zobrazí chyba týkající se neshody počtu pozičních parametrů. Tato notace funguje také s NDL, takže tuto změnu můžete nejprve provést a otestovat ji pomocí NDL před převodem. Toto je také dobrá příležitost přejmenovat jakékoli použití starší verze názvuLearnableParameter()
naParameterTensor{}
.Záleží také na
RowStack()
funkci , která v BrainScriptu přebírá jediný parametr, což je pole vstupů. Vstupy musí být oddělené dvojtečky (:
) místo čárky, napříkladRowStack (a:b:c)
místoRowStack (a, b, c)
.Aktualizovali jsme některé výchozí hodnoty, především volitelný
imageLayout
parametrConvolution()
, operace sdružování aImageInput()
. V případě NDL se jako výchozí hodnota použilalegacy
, zatímco výchozí hodnota jecudnn
teď, která musí být kompatibilní s primitivy konvoluce cuDNN. (Všechny ukázky kódu NDL tento parametr explicitně specifikují jakocudnn
již.)Analyzátor BrainScriptu je více omezující:
V identifikátorech se teď rozlišují malá a velká písmena. Předdefinované funkce používají PascalCase (např.
RectifiedLinear()
) a předdefinované proměnné a názvy parametrů používají camelCase (např.modelPath
,criterionNodes
), stejně jako řetězce možností (init="fixedValue"
,tag="criterion"
). Všimněte si, že u názvů volitelných parametrů není nesprávný pravopis vždy zachycen jako chyba. Místo toho se některé nesprávně napsané volitelné parametry prostě ignorují. Příkladem jsou definice speciálních uzlů. Jejich správná kontrola pravopisu je teď:featureNodes = ... labelNodes = ... criterionNodes = ... evaluationNodes = ... outputNodes = ...
Zkrácené alternativní názvy již nejsou povoleny, například
Const()
by měly být ,tag="eval"
měly byConstant()
býttag="evaluation"
aevalNodes
jsou teďevaluationNodes
.Byla opravena některá špatně napsaná jména:
criteria
is nowcriterion
(podobně),criterionNodes
defaultHiddenActivity
je teďdefaultHiddenActivation
.Znaménko
=
už není volitelné pro definice funkcí.I když je povoleno používat hranaté závorky pro bloky (
[ ... ]
), je zastaralá. Používejte složené závorky ({ ... }
).Popisky možností musí být uvozovány jako řetězce, například
init="uniform"
místoinit=uniform
. Bez uvozovek BrainScript selže s chybovou zprávou, že symboluniform
je neznámý.Primitiva BrainScriptu, která vytvářejí parametry (
Input{}
aParameterTensor{}
), by měla pro argumenty používat složené závorky (např.f = Input{42}
). Jedná se o konvenci, která se nevynucuje, ale doporučuje se do budoucna.
Tato omezenější syntaxe je stále přijímána
NDLNetworkBuilder
, proto doporučujeme nejprve provést tyto syntaktické změny a otestovat je pomocí NDL, než se skutečně změní na BrainScript.
Krok 4: Odeberte NDLNetworkBuilder
z oddílů "write" a "test". Přečtěte si prosím oddíly "write" a "test" a NDLNetworkBuilder
odeberte je. Některé z našich ukázkových příkladů NDL mají nadbytečné NDLNetworkBuilder
oddíly. Nepoužívají se a neměly by tam být. Pokud je vaše konfigurace založená na jednom z těchto příkladů, můžete mít i takové oddíly. Dřív se ignorovaly, ale po aktualizaci BrainScriptu má teď definování nové sítě v těchto oddílech význam (úpravy modelu), takže se už nebudou ignorovat, a proto by se měly odebrat.
NDLNetworkBuilder
reference (zastaralé)
Syntaxe zastaralého NDLNetworkBuilder
objektu je:
NDLNetworkBuilder = [
networkDescription = "yourNetwork.ndl"
]
Blok NDLNetworkBuilder
má následující parametry:
networkDescription
: cesta k souboru popisu sítě. U zastaraléhoNDLNetworkBuilder
souboru bylo obvyklé používat příponu.ndl
souboru . Pokud není zadaný žádnýnetworkDescription
parametr, předpokládá se, že popis sítě je vložený ve stejnémNDLNetworkBuilder
dílčím bloku zadaném pomocí parametrurun
níže. Všimněte si, že prostřednictvím parametrunetworkDescription
může být zadána pouze jedna cesta k souboru. Pokud chcete načíst více souborů maker, použijtendlMacros
parametr .run
: blok NDL, který se spustí. Pokud je externí soubor NDL zadán prostřednictvím parametrunetworkDescription
,run
parametr identifikuje blok v tomto souboru. Tento parametr přepíše všechnyrun
parametry, které již mohou v souboru existovat. Pokud není zadán žádnýnetworkDescription
soubor,run
parametr identifikuje blok v aktuálním konfiguračním souboru.load
: bloky skriptů NDL, které se mají načíst. Více bloků je možné zadat prostřednictvím odděleného seznamu ":". Bloky určené parametremload
obvykle obsahují makra pro použití vrun
bloku.run
Podobně jako parametrload
identifikuje bloky v externím souboru NDL a přepíše všechnyload
parametry, které už v souboru existují, pokud je soubor zadaný parametremnetworkDescription
. Pokud není zadán žádnýnetworkDescription
soubor,load
identifikuje blok v aktuálním konfiguračním souboru.ndlMacros
: Cesta k souboru, kam se můžou načíst makra NDL. Tento parametr se obvykle používá k načtení výchozí sady maker NDL, které můžou používat všechny skripty NDL. Více souborů NDL, z nichž každý určuje různé sady maker, lze načíst zadáním seznamu "+" oddělených cest k souborům pro tentondlMacros
parametr. Chcete-li sdílet makra s jinými bloky příkazů, jako jsou bloky jazyka pro úpravy modelu (MEL) NDL, měli byste je definovat na kořenové úrovni konfiguračního souboru.randomSeedOffset
: nezáporná hodnota náhodného počátečního posunu při inicializaci učitelných parametrů. Výchozí hodnota je0
. To umožňuje uživatelům spouštět experimenty s různými náhodnými inicializacemi.