Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Funkce představují způsob vytváření opakovaně použitelných modulů v BrainScriptu. Funkce jsou parametrizované výrazy a lze je definovat přímo dopředu, například:
Sqr (x) = x * x
Funkce jsou datové typy první třídy v tom smyslu, že funkce můžou přijímat a vracet další funkce.
Definování funkcí
Existují dva způsoby definování funkcí, standardní syntaxe a anonymní syntaxe lambda.
Standardní syntaxe
Pojmenované funkce jsou členy záznamů, které jsou definované jako přiřazení členů záznamů těchto dvou formulářů:
f (arg1, arg2, ..., optionalArg1=optionalArg1Default, ...) = expression of args
f {arg1, arg2, ..., optionalArg1=optionalArg1Default, ...} = expression of args
Tyto dva formuláře jsou syntakticky identické, ale druhý tvar (pomocí složených závorek{ }) se používá pro funkce, které vrací objekty funkcí s integrovanými naučnými parametry, jako jsou předdefinované vrstvy CNTK.
Argumenty funkce vytvoří obor názvů, jako je záznam; Tj. argumenty funkce jsou tak, jako by byly definovány jako členy v uzavřeném záznamu.
Volitelné parametry
Funkce můžou mít volitelné parametry. Tyto hodnoty jsou předány před jejich hodnotou .name= Pokud není předán volitelný parametr, použije se jeho výchozí hodnota. V definici funkce jsou volitelné parametry deklarovány pomocí formuláře name=defaultValue.
Tady je příklad funkce Softplus, která přebírá volitelný parametr strmosti:
Softplus (x, steepness=1) =
if steepness == 1 # use the simpler formula if no steepness specified
then Log (Constant(1) + Exp (x)) # softplus(x)
else { # version with steepness: 1/s softplus (s x)
steepnessAsConstant = Constant (steepness)
y = Reciprocal (steepnessAsConstant) .* Softplus (steepnessAsConstant .* x)
# Note: .* denotes an elementwise product
}.y
Poznámka: Výchozí hodnoty volitelných parametrů nemají přístup k jiným parametrům. Například pokud u výše uvedené funkce Softplus máte proměnnou, která definuje strmost, kterou chcete funkci předat, stačí říct:
steepness = 4
z = Softplus (x, steepness=steepness)
kde první steepness je název parametru a druhá je výrazem pro předání hodnoty.
Názvy nebudou v konfliktu.
Syntaxe lambda
Kromě syntaxe definice funkce umožňuje BrainScript anonymní lambda pomocí syntaxe (x => f(x)), která je určena k napodobení jazyka C#. Následující dvě definice jsou ekvivalentní:
sqr(x) = x * x
sqr = (x => x * x)
Ve skutečnosti brainscriptový analyzátor interně transformuje druhou z nich do bývalé formy.
Syntaxe lambda je aktuálně omezená na jeden parametr a nepodporuje také volitelné parametry. Lambdas s více než jedním parametrem nebo s volitelnými parametry musí být definovány jako pojmenované funkce.
Vyvolání funkcí
Funkce se volají podle očekávání: Předáním argumentů v závorkách; a předání volitelných argumentů jako pojmenovaných parametrů Například samoobslužný stabilizátor (technika škálování poněkud podobná dávkové normalizaci) pomocí Softplus se strmostí 4 by se napsal s následujícími dvěma vyvoláním funkce:
beta = ParameterTensor {1, initValue=1}
xStabilized = x .* Softplus (beta, steepness=4)
Funkce se po vyvolání líně spouští. Konkrétně platí, že pokud funkce definuje parametry modelu uvnitř (tj. varianty ParameterTensor{} a jakékoli funkce, která ji volá uvnitř), každé vyvolání funkce přináší nezávislou instanci těchto parametrů modelu. Často se výsledek vyvolání funkce přiřadí proměnné nebo se předá jako argument funkce. Více použití takové hodnoty nemá za následek opakované provádění.
Čistota/referenční průhlednost
Ačkoli BrainScript má běžné funkce s funkčními jazyky, mějte na paměti, že funkce BrainScriptu nejsou zcela čisté, v tom může mít jeden velmi specifický vedlejší účinek: vytvoření instance nových parametrů modelu. Pokud 2 * sqr(x) je výraz například ekvivalentní výrazu sqr(x) + sqr(x) (s sqr(x) = x*x), není to případ pro 2 * ParameterTensor{N} vs. ParameterTensor{N} + ParameterTensor{N}.
Podle konvence použijte kulaté závorky, kde je zadána referenční průhlednost, ale složené závorky ( ){ } označují, kde není.
Funkce jako hodnoty
V BrainScriptu jsou funkce hodnotami. Pojmenovanou funkci lze přiřadit k proměnné a předat ji jako argument. Pojmenované funkce jsou vlastně jen členy záznamů, které mají typ "funkce". Vyhledávání názvů funkcí je stejné jako vyhledávání členů záznamu. To umožňuje například seskupit funkce do "oborů názvů" tak, že je definujete uvnitř výrazu záznamu.
Pojmenované funkce jako hodnoty
Pokud se název funkce používá bez následujících závorek, bude odkazovat na samotnou funkci jako objekt.
Částečná aplikace nebo currying
BrainScript v současné době nemá syntaktickou podporu částečné aplikace nebo zakřivení. Pokud chcete dosáhnout podobného efektu, můžete definovat novou funkci, která volá jinou funkci s vázanými/zachycenými parametry:
Layer (x, m, n, f) = f (ParameterTensor {(m:n)} * x + ParameterTensor {n})
Sigmoid512Layer (x) = Layer (x, 512, 512, Sigmoid)
Příklady
Následující příklad definuje jednoduchou hierarchii běžných typů síťových vrstev:
Layers = {
# base feed-forward without and with parameterized energy function
# AffineLayer() defines model parameters inside.
AffineLayer (x, m, n) = ParameterTensor {(m:n), init='heNormal'} * x
+ ParameterTensor {n, initValue=0}
# NLLayer applies a non-linearity on top of an affine layer
NLLayer (x, m, n, f) = f (AffineLayer (x, m, n))
# a few non-linearities
SigmoidLayer (x, m, n) = NLLayer (x, m, n, Sigmoid) # pass Sigmoid() function as the non-linaerity
SoftplusLayer (x, m, n) = NLLayer (x, m, n, (x => Log (Constant(1) + Exp(x)))/*Softplus as lambda*/)
ReLULayer (x, m, n) = NLLayer (x, m, n, RectifiedLinear)
SoftmaxLayer (x, m, n) = NLLayer (x, m, n, Softmax)
}
které se dají použít takto:
# constants defined
# Sample, Hidden, and Label dimensions
SDim = 28*28 # feature dimension
HDim = 256 # hidden dimension
LDim = 10 # number of classes
features = Input {SDim}
labels = Input {LDim}
# layers
h = Layers.ReLULayer (features, HDim, SDim)
z = Layers.AffineLayer (h, LDim, HDim) # input to softmax; same as log softmax without normalization
# output and criteria
P = Softmax (z)
ce = CrossEntropyWithSoftmax (labels, z)
errs = ErrorPrediction (labels, z)
featureNodes = (features)
labelNodes = (labels)
criterionNodes = (ce)
evaluationNodes = (errs)
outputNodes = (P)
To je stejné jako počáteční příklad v základních konceptech, ale použití funkcí.
Další: Přečtěte si o úpravách modelu nebo přejděte přímo na úplný odkaz na funkce.
NDLNetworkBuilder (zastaralé)
Starší verze CNTK používaly NDLNetworkBuilder nyní zastaralé místo BrainScriptNetworkBuilder. NDLNetworkBuilderDefinice funkce se liší několika způsoby. Následující definice je platná v NDLNetworkBuilder:
FF (X1, W1, B1) # no equal sign
[ # both curly braces and brackets are allowed
T = Times (W1, X1)
FF = Plus (T, B1)
] # return value is FF, and not the entire record
Zvlášť je vrácena návratová hodnota prostřednictvím místní proměnné, která má stejný název jako funkce; nebo pokud nebyla nalezena žádná taková proměnná, vrátí se proměnná definovaná jako poslední. V BrainScriptu teď musí být napsané takto:
FF (X1, W1, B1) =
{
T = Times (W1, X1)
Y = Plus (T, B1)
}.Y
Zvlášť musí být vrácená hodnota Y explicitně vybrána na konci pomocí . syntaxe, jinak by hodnota funkce byla celý záznam.