BrainScript를 사용하여 모델 편집

(참고: 이전 버전의 CNTK 이 용도로 "MEL"(모델 편집 언어)을 사용했습니다. 예제를 변환하는 중입니다. MEL에 대한 설명서는 여기를 참조하세요.)

CNTK 팩트 후에 모델을 편집할 수 있습니다. 이 작업은 수정 사항이 적용된 기존 모델을 복제(일부)하는 동안 새 모델을 만들어 수행합니다. 이를 위해 CNTK 세 가지 기본 함수를 제공합니다.

  • BS.Network.Load() 기존 모델을 로드하려면
  • BS.Network.CloneFunction() 재사용을 위해 기존 모델의 섹션을 추출하려면
  • BS.Network.Edit() 노드별 수정이 적용된 모델을 복제하려면

편집 작업은 별도의 단계가 아닙니다. 오히려 수정된 모델에서 작동해야 하는 명령은 모델을 로드할 수 있는 modelPath 명령이 BrainScriptNetworkBuilder 아니라 모델을 내부에 로드하고 로드된 모델을 즉시 새 모델을 생성하는 섹션을 지정합니다.

예: 차별 사전 학습

차별적 사전 학습은 일련의 얕은 네트워크를 학습하여 심층 네트워크를 만드는 기술입니다. 숨겨진 1개 계층 네트워크로 시작하고 부분 수렴으로 학습한 다음 출력 계층을 제거하고 숨겨진 새 계층을 추가하고 새 출력 계층을 추가합니다. 원하는 수의 숨겨진 레이어에 도달할 때까지 반복합니다.

매우 간단한 시작 모델로 가정해 보겠습니다.

BrainScriptNetworkBuilder = [
    N = 40; M = 9000; H = 512
    W1   = Parameter (H, N); b1   = Parameter (H)
    Wout = Parameter (M, H); bout = Parameter (M)
    x = Input (N, tag=‘feature’) ; labels = Input (M, tag=‘labels’)
    h1 = Sigmoid (W1 * x  + b1)
    z  = Wout * h1 + bout
    ce = CrossEntropyWithSoftmax (labels, z, tag=‘criterion’)
]

이 모델을 학습하고 "model.1.dnn" 아래에 저장해 보겠습니다. 다음으로 두 개의 숨겨진 계층이 있는 모델을 학습하려고 합니다. 여기서 첫 번째 숨겨진 계층은 위에서 학습된 값에서 초기화됩니다. 이렇게 하려면 다음과 같이 새 모델을 만들지만 이전 모델의 일부를 다시 사용하는 별도의 학습 작업을 만듭니다.

BrainScriptNetworkBuilder = {
    # STEP 1: load 1-hidden-layer model
    inModel = BS.Network.Load ("model.1.dnn")
    # get its h1 variable --and also recover its dimension
    h1 = inModel.h1
    H = h1.dim
    # also recover the number of output classes
    M = inModel.z.dim

    # STEP 2: create the rest of the extended network as usual
    W2   = Parameter (H, H); b2   = Parameter (H)
    Wout = Parameter (M, H); bout = Parameter (M)
    h2 = Sigmoid (W2 * h1  + b2)
    z  = Wout * h2 + bout
    ce = CrossEntropyWithSoftmax (labels, z, tag=‘criterion’)
}

첫째, 1단계는 네트워크를 BrainScript 변수에 로드하는 데 사용합니다 Load() . 네트워크는 모든 최상위 노드(노드 이름에 포함되지 .[ 않은 모든 노드)가 레코드 구문을 통해 액세스할 수 있는 BrainScript 레코드처럼 작동합니다. 새 네트워크는 로드된 네트워크의 모든 노드를 참조할 수 있습니다. 이 예제에서 로드된 네트워크에는 첫 번째 숨겨진 계층의 출력인 노드 h1 와 출력 클래스(Softmax 함수에 대한 입력)의 비정규화되지 않은 로그 후방 확률인 노드 z 가 포함됩니다. 두 노드 모두 BrainScript에서 점 구문(예: inModel.h1inModel.z)을 통해 액세스할 수 있습니다.

상수는 모델에 저장되지 않으므로 N 모델에서 사용할 수 없습니다 M . 그러나 로드된 모델에서 다시 구성할 수 있습니다. 이를 위해 계산 노드는 BrainScript 레코드처럼 동작하고 속성을 노출합니다 dim .

다음으로, 2단계는 일반 BrainScript를 사용하여 새 네트워크의 나머지 부분을 구성합니다. 이 새 섹션에서는 다른 노드 h1 를 사용하는 것처럼 입력 모델의 노드를 입력으로만 사용합니다. 입력 네트워크에서 노드를 참조하면 이 노드가 새로 만든 네트워크의 일부에 의존하는 모든 노드가 자동으로 만들어집니다. 예를 들어 입력 노드 x 는 자동으로 새 네트워크의 일부가 됩니다.

또한 출력 계층이 새로 생성됩니다. 이렇게 하면 모델 매개 변수가 새로 만들어집니다. (이렇게 하지 않고 기존 매개 변수를 다시 사용하려면 이 inModel.Wout특정 예제의 네트워크 디자인 관점에서는 의미가 없습니다.)

예: 미리 학습된 모델 사용

다음은 미리 학습된 모델(파일 "./featext.dnn")을 기능 추출기로 사용하는 예제입니다.

BrainScriptNetworkBuilder = {
    # STEP 1: load existing model
    featExtNetwork = BS.Network.Load ("./featext.dnn")

    # STEP 2: extract a read-only section that is the feature extractor function
    featExt = BS.Network.CloneFunction (
                  featExtNetwork.input,    # input node that AE model read data from
                  featExtNetwork.feat,     # output node in AE model that holds the desired features
                  parameters="constant")   # says to freeze that part of the network

    # STEP 3: define the part of your network that uses the feature extractor
    # from the loaded model, which above we isolated into featExt().
    # featExt() can be used like any old BrainScript function.
    input = Input (...)
    features = featExt (input)  # this will instantiate a clone of the above network

    # STEP 4: and add the remaining bits of the network in BrainScript, e.g.
    h = Sigmoid (W_hid * features + b_hid) # whatever your hidden layer looks like
    z = W_out * h + b_out
    ce = CrossEntropyWithSoftmax (labels, z)
    criterionNodes = (ce)
}

1단계는 네트워크를 BrainScript 변수에 로드하는 데 사용합니다 Load() .

2단계에서는 연결된 하위 그래프인 로드된 네트워크에서 기능 추출 관련 섹션을 복제하는 featExtNetwork.inputfeatExtNetwork.feat사용합니다CloneFunction(). 지정했 parameters="constant"으므로 의존하는 모든 매개 변수 featExtNetwork.feat 도 복제되고 읽기 전용으로 만들어집니다.

3단계와 4단계에서 새 네트워크가 정의됩니다. 이 작업은 다른 BrainScript 모델과 마찬가지로 수행되며, 이제 함수를 featExt() 사용할 수 있습니다.

및 노드 이름 .[ 에 대한 문제 ]

해당 문자를 _포함 . 하거나 []대체한 네트워크의 노드를 참조하려면 . 예를 들어 호출 result.znetwork.result.z 된 노드가 포함된 경우 network 실패합니다. 대신 다음과 같이 말합니다network.result_z.

예: 기존 네트워크의 노드 수정

기존 네트워크의 내부 부분을 수정하려면 실제로 네트워크를 복제하는 반면 수정은 복제 프로세스의 일부로 적용됩니다. 이 작업은 .에 의해 BS.Network.Edit()수행됩니다. Edit() 는 네트워크의 모든 노드를 반복하며 호출자가 전달한 람다 함수에 각 노드를 하나씩 제공합니다. 그런 다음 이러한 람다 함수는 노드를 검사하고 수정되지 않은 노드를 반환하거나 해당 위치에 새 노드를 반환할 수 있습니다. Edit() 는 지정되지 않은 순서로 노드를 반복합니다. 대체 노드가 대체된 Edit() 네트워크 노드를 참조하는 경우 최종 단계로 해당 교체에 대한 이러한 모든 참조를 업데이트합니다(즉, "올바른 작업 수행").

TODO: 예제입니다.

다음: 전체 함수 참조