Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Benutzerdefinierte Netzwerke werden in der benutzerdefinierten Netzwerkbeschreibungssprache "BrainScript" von CNTK beschrieben. Um ein benutzerdefiniertes Netzwerk zu definieren, fügen Sie einen Abschnitt mit dem Namen BrainScriptNetworkBuilder in Ihre Trainingskonfiguration ein. Eine ausführliche Beschreibung der Netzwerkbeschreibungssprache finden Sie auf der Seite Grundlegende Konzepte und den entsprechenden Unterseiten.
Es gibt zwei Formen der Verwendung des BrainScript-Netzwerk-Generators: eine mit Klammern (...)und ein kurzhandformular mit geschweiften Klammern {...}. Um Ihr Netzwerk in einer externen Datei zu beschreiben, geben Sie einen Block ähnlich dem folgenden an:
BrainScriptNetworkBuilder = (new ComputationNetwork {
include "yourNetwork.bs"
})
wobei yourNetwork.bs das mit BrainScript beschriebene Netzwerk enthält. Die Datei yourNetwork.bs wird zuerst im selben Verzeichnis wie die Konfigurationsdatei und, falls nicht gefunden, im Verzeichnis der ausführbaren CNTK-Datei gesucht. Hier werden sowohl absolute als auch relative Pfadnamen akzeptiert. Bedeutet z. B. eine Datei, bs/yourNetwork.bs die sich in einem Verzeichnis bs neben Ihrer Konfigurationsdatei befindet (oder alternativ ein Verzeichnis bs im ausführbaren Verzeichnis CNTK).
Hinweis: Bis CNTK 1.6 verwendete BrainScript Klammern [...] anstelle von geschweiften Klammern {...}. Klammern sind weiterhin akzeptiert, aber veraltet.
Alternativ können Sie Ihr Netzwerk direkt in der Konfigurationsdatei inline definieren. Dies kann die Konfiguration vereinfachen, wenn Sie nicht planen, dasselbe Gehirnskript für mehrere Konfigurationen zu verwenden. Verwenden Sie dieses Formular:
BrainScriptNetworkBuilder = {
# insert network description here
}
Wie sieht also der BrainScript-Code aus, der in die Klammern geht? Um dies herauszufinden, springen Sie direkt zu BrainScript Basic Concepts.
Oder bleiben Sie auf dieser Seite und lesen Sie einige weniger häufig benötigte Details für Sie.
Die {...} obige Form ist wirklich nur eine Kurze dafür:
BrainScriptNetworkBuilder = (new ComputationNetwork {
# insert network description here
})
Schließlich ist das (...) Formular als erweiterte Verwendung nicht auf die Verwendung newbeschränkt. Vielmehr ist jeder BrainScript-Ausdruck, der zu einem Objekt von ComputationNetwork auswertet, innerhalb der Klammern zulässig. Beispiel:
BrainScriptNetworkBuilder = ({
include "myNetworks.bs"
network = CreateMyNetworkOfType42()
}.network)
Dies ist eine erweiterte Verwendung, die manchmal auch im Kontext der Modellbearbeitung auftritt.
Weiter: Grundlegende Konzepte von BrainScript.
Hinterlassenschaft NDLNetworkBuilder
In älteren Versionen von CNTK hieß NDLNetworkBuilderder Netzwerk-Generator . Die Definitionssprache ist eine Teilmenge von BrainScript. Der alte Parser war weniger fähig, aber auch verzeihend. Es gibt auch andere kleine Unterschiede.
NDLNetworkBuilder ist jetzt veraltet, aber aufgrund der Ähnlichkeit ist es nicht schwierig, auf zu BrainScriptNetworkBuilderaktualisieren. Im Folgenden finden Sie eine Anleitung zum Konvertieren von NDLNetworkBuilder Netzwerkbeschreibungen in BrainScriptNetworkBuilder's.
Aktualisieren von von auf NDLNetworkBuilderBrainScriptNetworkBuilder
Das Konvertieren einer vorhandenen Netzwerkdefinition für den ist BrainScriptNetworkBuilder in den NDLNetworkBuilder meisten Fällen einfach. Die Standard Änderungen sind die umgebende Syntax. Die Kernnetzwerkbeschreibung selbst ist weitgehend nach oben kompatibel und wahrscheinlich identisch oder nahezu identisch, wenn Sie die neuen Sprachfeatures nicht nutzen.
Um Ihre Beschreibungen zu konvertieren, müssen Sie den Netzwerk-Generator wechseln, die äußere Syntax anpassen und möglicherweise kleinere Anpassungen an Ihren Netzwerkcode selbst vornehmen.
Schritt 1: Wechseln des Netzwerk-Generators. Ersetzen Sie durch NDLNetworkBuilder den entsprechenden BrainScriptNetworkBuilder Block in der CNTK-Konfigurationsdatei. Wenn sich Ihre Netzwerkbeschreibung in einer separaten Datei befindet:
# change from:
NDLNetworkBuilder = [
ndlMacros = "shared.ndl" # (if any)
networkDescription = "yourNetwork.ndl"
]
# ...to:
BrainScriptNetworkBuilder = (new ComputationNetwork {
include "shared.bs" # (if any)
include "yourNetwork.bs"
})
(Die Änderung der Dateinamenerweiterung ist nicht unbedingt erforderlich, aber empfohlen.)
Wenn sich Ihre Netzwerkbeschreibung in der .cntk Konfigurationsdatei selbst befindet:
# 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")
}
Schritt 2: Entfernen und loadrun blockieren. Mit BrainScriptNetworkBuilderwerden Makro-/Funktionsdefinitionen und Standard Code kombiniert. Die load Blöcke und run müssen einfach entfernt werden. So wird beispielsweise
load = ndlMnistMacros
run = DNN
ndlMnistMacros = [
featDim = 784
...
labels = InputValue(labelDim)
]
DNN = [
hiddenDim = 200
...
outputNodes = (ol)
]
wird einfach:
featDim = 784
...
labels = InputValue(labelDim)
hiddenDim = 200
...
outputNodes = (ol)
Möglicherweise haben Sie die run Variable verwendet, um eine von mehreren Konfigurationen mit einer externen Variablen auszuwählen, z. B.:
NDLNetworkBuilder = [
run = $whichModel$ # outside parameter selects model, must be either "model1" or "model2"
model1 = [ ... (MODEL 1 DEFINITION) ]
model2 = [ ... (MODEL 1 DEFINITION) ]
]
Dieses Muster war hauptsächlich erforderlich, da NDL keine bedingten Ausdrücke hatte. In BrainScript wird dies nun mit einem if Ausdruck geschrieben:
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$'")
)
Häufig ähneln sich die ausgewählten Modelle jedoch sehr, sodass eine bessere Möglichkeit darin besteht, ihre Beschreibungen zusammenzuführen und stattdessen Nur dort Bedingungen zu verwenden, wo sie sich unterscheiden. Hier sehen Sie ein Beispiel, in dem ein Parameter verwendet wird, um zwischen einem unidirektionalen und einem bidirektionalen LSTM zu wählen:
encoderFunction =
if useBidirectionalEncoder
then BS.RNNs.RecurrentBirectionalLSTMPStack
else BS.RNNs.RecurrentLSTMPStack
encoder = encoderFunction (encoderDims, inputEmbedded, inputDim=inputEmbeddingDim)
Schritt 3: Anpassen der Netzwerkbeschreibung. In Bezug auf die Netzwerkbeschreibung (Formeln) selbst ist BrainScript weitgehend kompatibel mit NDL. Dies sind die Standard Unterschiede:
Der Rückgabewert von Makros (Funktionen) ist nicht mehr die letzte darin definierte Variable, sondern der gesamte Satz von Variablen. Sie müssen den Ausgabewert am Ende explizit auswählen. Beispiel:
# 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 dereferencedOhne diese Änderung wäre der Funktionsrückgabewert der gesamte Datensatz, und der typische Fehler, den Sie erhalten, ist, dass erwartet
ComputationNodewurde, wo einComputationNetworkgefunden wurde.BrainScript lässt keine Funktionen mit variabler Anzahl von Parametern zu. Dies ist in erster Linie für die
Parameter()Funktion wichtig: Ein Vektorparameter kann nicht mehr alsParameter(N)geschrieben werden, er muss nun explizit als TensorParameterTensor{N}oder als 1-Spalten-MatrixParameter(N, 1)geschrieben werden. Ohne diese Änderung erhalten Sie eine Fehlermeldung über die nicht übereinstimmende Anzahl von Positionsparametern. Diese Notation funktioniert auch mit NDL, sodass Sie diese Änderung zuerst vornehmen und vor der Konvertierung mit NDL testen können. Dies ist auch eine gute Gelegenheit, alle Verwendungen des LegacynamensLearnableParameter()in umzubenennenParameterTensor{}.Es ist auch für die
RowStack()Funktion wichtig, die in BrainScript einen einzelnen Parameter akzeptiert, der ein Array von Eingaben ist. Die Eingaben müssen durch einen Doppelpunkt (:) anstelle eines Kommas getrennt sein, z. B.RowStack (a:b:c)anstelle vonRowStack (a, b, c).Einige Standardwerte wurden aktualisiert, vor allem der optionale
imageLayoutParameter vonConvolution(), die Poolvorgänge undImageInput(). Für NDL sind diese standardmäßig auflegacyfestgelegt, während der Standardwert jetzt erforderlich istcudnn, um mit den cuDNN-Convolution-Primitiven kompatibel zu sein. (Alle NDL-Codebeispiele geben diesen Parameter explizit an.cudnn)Der BrainScript-Parser ist restriktiver:
Bei Bezeichnern wird jetzt die Groß-/Kleinschreibung beachtet. Integrierte Funktionen verwenden PascalCase (z. B.
RectifiedLinear()), und integrierte Variablen und Parameternamen verwenden camelCase (z. B.modelPath,criterionNodes), sowie Optionszeichenfolgen (init="fixedValue",tag="criterion"). Beachten Sie, dass bei Namen optionaler Parameter falsche Schreibweisen nicht immer als Fehler abgefangen werden. Stattdessen werden einige falsch geschriebene optionale Parameter einfach ignoriert. Ein Beispiel sind die Definitionen für spezielle Knoten. Ihre richtige Schreibweise für diese lautet jetzt:featureNodes = ... labelNodes = ... criterionNodes = ... evaluationNodes = ... outputNodes = ...Abgekürzte alternative Namen sind nicht mehr zulässig, z
Const(). BConstant(). sollten ,tag="eval"undtag="evaluation"evalNodesist jetztevaluationNodes.Einige falsch geschriebene Namen wurden korrigiert: ist jetzt
criterion(ebenso ),criterionNodesdefaultHiddenActivityist jetztdefaultHiddenActivation.criteriaDas
=Zeichen ist für Funktionsdefinitionen nicht mehr optional.Es ist zwar zulässig, Klammern für Blöcke (
[ ... ]) zu verwenden, ist jedoch veraltet. Verwenden Sie geschweifte Klammern ({ ... }).Optionsbezeichnungen müssen als Zeichenfolgen angegeben werden, z. B.
init="uniform"anstelle voninit=uniform. Ohne die Anführungszeichen schlägt BrainScript mit einer Fehlermeldung fehl, die besagt, dass das Symboluniformunbekannt ist.Die BrainScript-Grundtypen, die Parameter (
Input{}undParameterTensor{}) erstellen, sollten geschweifte Klammern für ihre Argumente verwenden (z. B.f = Input{42}). Dies ist eine Konvention, die nicht erzwungen, aber für die Zukunft empfohlen wird.
Diese eingeschränktere Syntax wird weiterhin von
NDLNetworkBuilderakzeptiert, daher wird empfohlen, zuerst diese syntaktischen Änderungen vorzunehmen und mit NDL zu testen, bevor Sie tatsächlich zu BrainScript wechseln.
Schritt 4. Entfernen Sie NDLNetworkBuilder aus den Abschnitten "Schreiben" und "Testen". Überprüfen Sie die Abschnitte NDLNetworkBuilder "Schreiben" und "Testen", und entfernen Sie sie. Einige unserer Bestands-NDL-Beispiele haben zusätzliche NDLNetworkBuilder Abschnitte. Sie werden nicht verwendet und sollten nicht vorhanden sein. Wenn Ihre Konfiguration auf einem dieser Beispiele basiert, verfügen Sie möglicherweise auch über solche Abschnitte. Sie wurden früher ignoriert, aber mit dem BrainScript-Update hat das Definieren eines neuen Netzwerks in diesen Abschnitten jetzt eine Bedeutung (Modellbearbeitung), sodass sie nicht mehr ignoriert werden und daher entfernt werden sollten.
NDLNetworkBuilder Referenz (veraltet)
Die Syntax des veralteten NDLNetworkBuilder lautet:
NDLNetworkBuilder = [
networkDescription = "yourNetwork.ndl"
]
Der NDLNetworkBuilder Block verfügt über die folgenden Parameter:
networkDescription: der Dateipfad der Netzwerkbeschreibungsdatei. Mit dem veraltetenNDLNetworkBuilderwar es üblich, die Dateierweiterung.ndlzu verwenden. Wenn keinnetworkDescriptionParameter angegeben ist, wird davon ausgegangen, dass die Netzwerkbeschreibung in denselbenNDLNetworkBuilderTeilblock eingeteilt wird, der mit demrunfolgenden Parameter angegeben wird. Beachten Sie, dass nur ein Dateipfad über dennetworkDescriptionParameter angegeben werden kann. Verwenden Sie denndlMacrosParameter, um mehrere Makrodateien zu laden.run: der Block der ausgeführten NDL. Wenn über dennetworkDescriptionParameter eine externe NDL-Datei angegeben wird, identifiziert derrunParameter einen Block in dieser Datei. Dieser Parameter überschreibt allerunParameter, die möglicherweise bereits in der Datei vorhanden sind. Wenn keinenetworkDescriptionDatei angegeben ist, identifiziert derrunParameter einen Block in der aktuellen Konfigurationsdatei.load: die zu ladenden Blöcke von NDL-Skripts. Mehrere Blöcke können über eine durch ":" getrennte Liste angegeben werden. Die durch den Parameter angegebenen Blöcke enthalten in derloadRegel Makros zur Verwendung durch denrunBlock. Ähnlich wie derrunParameter identifiziert derloadParameter Blöcke in einer externen NDL-Datei und überschreibt alleloadParameter, die möglicherweise bereits in der Datei vorhanden sind, wenn eine Datei durch dennetworkDescription-Parameter angegeben wird. Wenn keinenetworkDescriptionDatei angegeben ist,loadidentifiziert einen Block in der aktuellen Konfigurationsdatei.ndlMacros: Der Dateipfad, in den NDL-Makros geladen werden können. Dieser Parameter wird normalerweise verwendet, um einen Standardsatz von NDL-Makros zu laden, die von allen NDL-Skripts verwendet werden können. Mehrere NDL-Dateien, die jeweils unterschiedliche Makrosätze angeben, können geladen werden, indem sie eine getrennte Liste von Dateipfaden mit "+" für diesenndlMacrosParameter angeben. Um Makros mit anderen Befehlsblöcken wie den MEL-Blöcken (Model Editing Language) von NDL freizugeben, sollten Sie sie auf der Stammebene der Konfigurationsdatei definieren.randomSeedOffset: Ein nicht negativer Zufälliger Startoffsetwert beim Initialisieren der lernbaren Parameter. Standardwert:0. Dadurch können Benutzer Experimente mit unterschiedlicher zufälliger Initialisierung ausführen.