BrainScript 기본 개념

BrainScript--A Walk-Through

이 섹션에서는 "BrainScript" 언어의 기본 개념을 소개합니다. 새 언어인가요? & 읽는 것을 걱정하지 마십시오, 그것은 매우 똑바로 앞으로.

CNTK에서 사용자 지정 네트워크는 를 사용하여 BrainScriptNetworkBuilder 정의되며 CNTK 네트워크 설명 언어 "BrainScript"에 설명되어 있습니다. 마찬가지로 네트워크 설명을 브레인 스크립트라고 합니다.

BrainScript는 식, 변수, 기본 및 자체 정의 함수, 중첩 블록 및 기타 잘 이해된 개념을 사용하여 코드와 같은 방식으로 네트워크를 정의하는 간단한 방법을 제공합니다. 구문의 스크립팅 언어와 유사합니다.

좋아, 전체 BrainScript 예제와 함께 우리의 발을 젖은 얻을 수 있습니다!

전체 BrainScript 예제 네트워크 정의

다음 예제에서는 숨겨진 계층 하나와 분류 계층이 하나씩 있는 간단한 신경망에 대한 네트워크 설명을 보여줍니다. 이 예제의 개념을 설명합니다. 계속 진행하기 전에 몇 분 동안 예제를 사용하여 그 의미를 추측해 볼 수 있습니다. 당신은 찾을 수 있습니다., 당신이 읽은 대로, 당신은 제대로 그것의 대부분을 추측.

BrainScriptNetworkBuilder = {   # (we are inside the train section of the CNTK config file)

    SDim = 28*28 # feature dimension
    HDim = 256   # hidden dimension
    LDim = 10    # number of classes

    # define the model function. We choose to name it 'model()'.
    model (features) = {
        # model parameters
        W0 = ParameterTensor {(HDim:SDim)} ; b0 = ParameterTensor {HDim}
        W1 = ParameterTensor {(LDim:HDim)} ; b1 = ParameterTensor {LDim}

        # model formula
        r = RectifiedLinear (W0 * features + b0) # hidden layer
        z = W1 * r + b1                          # unnormalized softmax
    }.z

    # define inputs
    features = Input {SDim}
    labels   = Input {LDim} 

    # apply model to features
    z = model (features)

    # define criteria and output(s)
    ce   = CrossEntropyWithSoftmax (labels, z)  # criterion (loss)
    errs = ErrorPrediction         (labels, z)  # additional metric
    P    = Softmax (z)     # actual model usage uses this

    # connect to the system. These five variables must be named exactly like this.
    featureNodes    = (features)
    inputNodes      = (labels)
    criterionNodes  = (ce)
    evaluationNodes = (errs)
    outputNodes     = (P)
}

BrainScript 구문 기본 사항

자세히 살펴보기 전에 BrainScript의 구문에 대한 몇 가지 일반적인 정보를 제공합니다.

BrainScript는 수학 수식처럼 보이는 방식으로 신경망을 표현할 수 있도록 하는 간단한 구문을 사용합니다. 따라서 기본 구문 단위는 변수 할당과 함수 정의 모두에서 사용되는 할당입니다. 예를 들면 다음과 같습니다.

Softplus (x) = Log (1 + Exp (x))
h = Softplus (W * v + b)

줄, 메모, 포함

대입은 일반적으로 한 줄로 작성되지만 식은 여러 줄에 걸쳐 있습니다. 그러나 여러 할당을 한 줄에 배치하려면 세미콜론으로 구분해야 합니다. 예를 들면 다음과 같습니다.

SDim = 28*28 ; HDim = 256 ; LDim = 10    # feature, hidden, and label dimension

줄 바꿈이 없는 경우 할당 간에 세미콜론을 요구하는 것 외에 BrainScript는 공백을 구분하지 않습니다.

BrainScript는 Python 스타일과 C++스타일 # 를 모두 사용하여 줄 끝 주석을 //이해합니다. 인라인 주석은 C 구문(/* this is a comment*/)을 사용하지만 C와 달리 여러 줄에 걸쳐 있지 않을 수 있습니다.

CNTK 구성 파일에 포함된 BrainScript(지시문을 통해 include 별도의 파일에서 읽는 BrainScript와 반대)의 경우 구성 파서와의 상호 작용으로 인해 C/C++ 스타일 주석 및 문자열 리터럴 내에서 괄호, 중괄호 또는 대괄호를 균형 조정해야 하는 (다소 이상한) 추가 제한이 있습니다. 따라서 C/C++스타일의 주석에는 웃는 얼굴도 없습니다!

지시문은 include "PATH" 문의 지점에서 파일의 내용을 삽입하는 모든 위치에서 사용할 수 있습니다. 여기서 는 PATH 절대 또는 상대 상대 경로(하위 디렉터리를 포함하거나 사용하지 않음)일 수 있습니다. 상대 경로인 경우 다음 위치가 순서대로 검색됩니다. 현재 작업 디렉터리; 파일이 포함된 외부를 포함하는 디렉터리(있는 경우) 구성 파일을 포함하는 디렉터리 마지막으로 CNTK 실행 파일을 포함하는 디렉터리입니다. 모든 기본 제공 BrainScript 함수는 CNTK 실행 파일 옆에 있는 라는 CNTK.core.bs 파일에서 이러한 방식으로 포함됩니다.

표현식

다음으로, 네트워크를 설명하는 수식인 BrainScript 식에 대해 알아야 합니다. BrainScript 식 은 인기 있는 프로그래밍 언어와 유사한 구문으로 수학과 유사하게 작성됩니다. 가장 간단한 식은 리터럴(예: 숫자 및 문자열)입니다. 수학과 유사한 예제는 입니다 W1 * r + b. 여기서 * 는 변수의 형식에 따라 스칼라, 행렬 또는 텐서 제품을 참조합니다. 식의 또 다른 일반적인 종류는 함수 호출입니다(예: ). RectifiedLinear (.)

BrainScript는 동적으로 형식화된 언어입니다. 중요한 식 형식은 구문을 사용하여 {...} 정의되고 점 구문을 통해 액세스되는 레코드입니다. 예를 들어 는 r = { x = 13 ; y = 42 } 두 멤버가 있는 레코드를 에 할당합니다 r. 여기서 첫 번째 멤버는 로 r.x액세스할 수 있습니다.

일반적인 수학 연산자 외에도 BrainScript에는 조건식(if c then t else f), 배열 식 및 단순 람다가 있습니다. 마지막으로, CNTK C++ 코드와 상호 작용하기 위해 BrainScript는 미리 정의된 제한된 C++ 개체 집합을 직접 인스턴스화할 수 있으며, 주로 ComputationNode 계산 네트워크가 구성됩니다. 자세한 내용은 식을 참조하세요.

BrainScript 식은 처음 사용할 때 평가됩니다. BrainScript의 주요 목적은 네트워크를 설명하는 것이므로 식의 값은 종종 최종 값이 아니라 지연된 계산을 위한 계산 그래프의 노드()입니다 W1 * r + b. BrainScript가 구문 분석될 때 스칼라의 BrainScript 식(예: 28*28)만 '계산'됩니다. 사용되지 않는 식(예: 조건으로 인해)은 평가되지 않습니다.

참고: 이제 사용되지 않는 NDLNetworkBuilder 버전은 함수 호출 구문만 지원됩니다. 예를 들어 를 작성 Plus (Times (W1, r), b1)해야 합니다.

변수

변수는 BrainScript 식(number, string, record, array, lambda, CNTK C++ 개체)의 값을 보유할 수 있으며 식에서 사용할 때 대체됩니다. 변수는 변경할 수 없습니다. 즉, 한 번만 할당됩니다. 예를 들어 위의 네트워크 정의는 다음으로 시작합니다.

SDim = 28*28  
HDim = 256
LDim = 10

여기서 변수는 후속 식에서 매개 변수로 사용되는 스칼라 숫자 값으로 설정됩니다. 이러한 값은 학습에 사용되는 데이터 샘플, 숨겨진 계층 및 레이블의 차원입니다. 이 특정 예제 설정은 -픽셀 이미지의 [28 x 28]컬렉션인 MNIST 데이터 세트에 대한 것입니다. 각 이미지는 필기 숫자(0-9)이므로 각 이미지에 적용할 수 있는 10개의 가능한 레이블이 있습니다. 숨겨진 활성화 차원 HDim 은 사용자 선택입니다.

대부분의 변수는 레코드 멤버입니다(외부 BrainScript 블록은 암시적으로 레코드임). 또한 변수는 함수 인수이거나 배열 요소로 저장할 수 있습니다.

모델 정의를 진행할 준비가 된 것입니다.

네트워크 정의

네트워크는 주로 입력에서 네트워크의 출력을 계산하는 방법을 수식으로 설명합니다. 이를 BrainScript에서 실제 함수로 정의되는 모델 함수라고 합니다. 모델 함수의 일부로 사용자는 모델 매개 변수를 선언해야 합니다. 마지막으로 네트워크의 입력 및 조건/출력 정의해야 합니다. 이러한 모든 변수는 변수로 정의됩니다. 그런 다음 입력 및 조건/출력 변수를 시스템에 전달해야 합니다.

네트워크의 모델 함수 및 모델 매개 변수

모델 함수에는 실제 네트워크 수식과 해당 모델 매개 변수가 포함됩니다. 이 예제에서는 매트릭스 제품 및 더하기 및 에너지 함수에 대한 '기본'(기본 제공) 함수 RectifiedLinear()를 사용하므로 네트워크 함수의 핵심은 다음 수식으로 구성됩니다.

r = RectifiedLinear (W0 * features + b0)
z = W1 * r + b1 

모델 매개 변수 는 학습 완료 시 학습된 모델을 구성하는 행렬, 바이어스 벡터 또는 기타 텐서입니다. model-parameter 텐서는 입력 샘플 데이터를 원하는 출력으로 변환하는 데 사용되며 학습 프로세스에 의해 업데이트됩니다. 위의 예제 네트워크에는 다음 행렬 매개 변수가 포함되어 있습니다.

W0 = ParameterTensor {(HDim:SDim)}
b0 = ParameterTensor {(HDim)}

이 경우 는 W0 가중치 행렬이고 b0 는 바이어스 벡터입니다. ParameterTensor{} 는 벡터, 행렬 또는 임의 순위 텐서를 인스턴스화하고 차원 매개 변수를 BrainScript 배열(콜론 :으로 연결된 숫자)로 사용하는 특수 CNTK 기본 형식을 나타냅니다. 벡터의 차원은 단일 숫자이지만 행렬 차원은 로 (numRows:numCols)지정해야 합니다. 기본적으로 매개 변수는 직접 인스턴스화될 때와 heNormal계층을 통해 사용될 때 균일한 난수로 초기화되지만 전체 목록에 대한 다른 옵션(여기 참조)이 있습니다. 일반 함수와 달리 는 ParameterTensor{} 인수를 괄호 대신 중괄호로 사용합니다. 중괄호는 함수가 아닌 매개 변수 또는 개체를 만드는 함수에 대한 BrainScript 규칙입니다.

그러면 모두 BrainScript 함수로 래핑됩니다. BrainScript 함수는 형식 f(x) = an expression of x으로 선언됩니다. 예를 들어 는 Sqr (x) = x * x 유효한 BrainScript 함수 선언입니다. 훨씬 더 간단하고 직접적 일 수 없습니다, 오른쪽?

이제 위의 예제의 실제 모델 함수는 좀 더 복잡합니다.

model (features) = {
    # model parameters
    W0 = ParameterTensor {(HDim:SDim)} ; b0 = ParameterTensor {HDim}  
    W1 = ParameterTensor {(LDim:HDim)} ; b1 = ParameterTensor {LDim}

    # model formula
    r = RectifiedLinear (W0 * features + b0) # hidden layer
    z = W1 * r + b1                          # unnormalized softmax
}.z

외부 { ... } 와 그 결승전 .z 은 몇 가지 설명을받을 자격이. 외부 curlies { ... } 및 해당 콘텐츠는 실제로 6개 레코드 멤버(W0, , , b0b1W1, rz)가 있는 레코드를 정의합니다. 그러나 모델 함수의 값은 단지 z이고, 다른 모든 함수는 함수 내부입니다. 따라서 를 사용하여 .z 반환할 레코드 멤버를 선택합니다. 레코드 멤버에 액세스하기 위한 점 구문일 뿐입니다. 이렇게 하면 다른 레코드 멤버는 외부에서 액세스할 수 없습니다. 그러나 를 계산 z하는 식의 일부로 계속 존재합니다. 패턴은 { ... ; x = ... }.x 지역 변수를 사용하는 방법입니다.

레코드 구문은 필요하지 않습니다. 또는 레코드를 model(features) 통해 우회하지 않고 단일 식으로 선언할 수도 있습니다.

model (features) = ParameterTensor {(LDim:HDim)} * (RectifiedLinear (ParameterTensor {(HDim:SDim)}
                   * features + ParameterTensor {HDim})) + ParameterTensor {LDim}

읽기가 훨씬 더 어렵고, 더 중요한 것은 수식의 여러 위치에서 동일한 매개 변수를 사용할 수 없다는 것입니다.

입력

네트워크에 대한 입력은 샘플 데이터 및 샘플과 연결된 레이블에 의해 정의됩니다.

features = Input {SDim}
labels   = Input {LDim}

Input{} 는 모델 정의에 필요한 두 번째 특수 CNTK 기본 형식입니다(첫 번째는 Parameter{}). 네트워크 외부에서 읽기 권한자로부터 입력을 받는 변수를 만듭니다. 의 Input{} 인수는 데이터 차원입니다. 이 예제 features 에서 입력은 샘플 데이터의 차원(변수 SDim로 정의됨)을 가지며 labels 입력에는 레이블의 차원이 포함됩니다. 입력의 변수 이름은 판독기 정의의 해당 항목과 일치해야 합니다.

학습 조건 및 네트워크 출력

네트워크 출력이 전 세계와 상호 작용하는 방식을 선언해야 합니다. 모델 함수는 로그 값(정규화되지 않은 로그 확률)을 계산합니다. 이러한 로그 값을 사용하여

  • 학습 기준을 정의합니다.
  • 측정 정확도 및
  • 입력이 지정된 출력 클래스에 대한 확률을 계산하여 분류 결정을 기반으로 합니다(정규화되지 않은 로그 후방 z 을 분류에 직접 사용할 수 있음).

예제 네트워크는 하나의 핫 벡터로 표시되는 범주 레이블을 사용합니다. MNIST 예제의 경우 이러한 값은 10개 부동 소수점 값의 배열로 표시되며, 모두 1.0인 적절한 레이블 범주를 제외하고 모두 0입니다. 와 같은 분류 작업은 일반적으로 함수를 SoftMax() 사용하여 각 레이블에 대한 확률을 얻습니다. 그런 다음 네트워크는 올바른 클래스(교차 엔트로피)의 로그 확률을 최대화하고 다른 모든 클래스의 로그 확률을 최소화하도록 최적화됩니다. 이것이 학습 기준 또는 손실 함수입니다. CNTK에서 이러한 두 작업은 일반적으로 효율성을 위해 하나의 함수에서 결합됩니다.

ce = CrossEntropyWithSoftmax (labels, z)

CrossEntropyWithSoftmax() 함수는 입력을 사용하고, 함수를 SoftMax() 계산하고, 크로스 엔트로피를 사용하여 실제 값의 오류를 계산하며, 해당 오류 신호는 역 전파를 통해 네트워크의 매개 변수를 업데이트하는 데 사용됩니다. 따라서 위의 예제에서 로 계산P한 정규화된 Softmax() 값은 학습 중에 사용되지 않습니다. 그러나 네트워크를 사용하는 데 필요합니다(대부분의 경우 z 분류에 충분한 경우가 많으며, z 이 경우 그 자체가 출력이 됩니다).

CNTK는 학습 알고리즘으로 SGD(확률 그라데이션 하강) 를 사용합니다. SGD는 모든 모델 매개 변수와 관련하여 목표 함수의 그라데이션을 계산해야 합니다. 중요한 것은 CNTK에서 사용자가 해당 그라데이션을 지정할 필요가 없다는 것입니다. 대신 CNTK의 각 기본 제공 함수에는 파생 함수도 있고 시스템은 네트워크 매개 변수의 백 전파 업데이트를 자동으로 수행합니다. 사용자에게 표시되지 않습니다. 사용자는 그라데이션에 관심을 가질 필요가 없습니다. 적.

학습 기준 외에도 학습 단계 중에 예측된 오류율이 계산되어 학습이 더 진행됨에 따라 시스템 개선의 유효성을 검사합니다. 이 작업은 다음 함수를 사용하여 CNTK에서 처리됩니다.

errs = ClassificationError (labels, z)

네트워크에서 생성되는 확률은 실제 레이블과 비교되고 오류율이 계산됩니다. 이는 일반적으로 시스템에서 표시됩니다. 이는 유용하지만 를 사용해야 ClassificationError()하는 것은 아닙니다.

입력, 출력 및 조건을 시스템에 전달

이제 모든 변수가 정의되었으므로 입력, 출력 및 조건으로 처리해야 하는 변수 중 어느 것을 시스템에 알려야 합니다. 이 작업은 정확히 이러한 이름이 있어야 하는 5개의 특수 변수를 정의하여 수행됩니다.

featureNodes    = (features)
labelNodes      = (labels)
criterionNodes  = (ce)
evaluationNodes = (errs)
outputNodes     = (z:P)

값은 콜론으로 값을 구분해야 하는 배열입니다(콜론은 : 두 값 또는 배열을 연결하여 배열을 형성하는 BrainScript 연산자임). 이는 및 P 를 모두 z 출력으로 선언하는 에 대해 위에 outputNodes표시됩니다.

(참고: 사용되지 않는 NDLNetworkBuilder 경우 배열 요소를 대신 쉼표로 구분해야 했습니다.)

특수 이름 요약

위에서 본 것처럼 "매직" 속성을 포함하는 7개의 특수 이름을 알고 있어야 합니다.

  • ParameterTensor{}: 학습 가능한 매개 변수를 선언하고 초기화합니다.
  • Input{}: 데이터 판독기에서 연결되고 공급되는 변수를 선언합니다.
  • featureNodes, labelNodes, criterionNodes, evaluationNodes및 : 입력, 출력 및 outputNodes조건으로 사용할 변수를 시스템에 선언합니다.

또한 CNTK에 기본 제공되는 "매직"을 사용하는 3가지 특수 함수가 더 있습니다. 이 함수는 다른 곳에서 설명합니다.

  • Constant(): 상수를 선언합니다.
  • PastValue()FutureValue(): 양식 되풀이 루프에 대해 다른 시간 단계에서 네트워크 함수의 변수에 액세스합니다.

다른 미리 정의된 이름은 C++ 구현과 같은 Sigmoid()Convolution() 기본 제공 기본 함수, 와 같은 BS.RNNs.LSTMP()BrainScript에서 실현된 미리 정의된 라이브러리 함수 또는 라이브러리 함수의 네임스페이스 역할을 하는 레코드(예: BS.RNNs)입니다. 전체 목록은 BrainScript-Full-Function-Reference를 참조 하세요.

다음: BrainScript 식