(참고: 이전 버전의 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단계는 Load() 사용하여 네트워크를 BrainScript 변수로 로드합니다. 네트워크는 모든 최상위 노드(노드 이름에 . 또는 [ 포함하지 않는 모든 노드)가 레코드 구문을 통해 액세스할 수 있는 BrainScript 레코드처럼 동작합니다. 새 네트워크는 로드된 네트워크의 모든 노드를 참조할 수 있습니다. 이 예제에서 로드된 네트워크에는 첫 번째 숨겨진 계층의 출력인 노드 h1 출력 클래스(Softmax 함수에 대한 입력)의 비정규화되지 않은 로그 후방 확률인 노드 z 포함됩니다. 두 노드는 모두 inModel.h1 및 inModel.z같은 점 구문을 통해 BrainScript에서 액세스할 수 있습니다.
상수는 모델에 저장되지 않으므로 모델에서 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단계는 Load() 사용하여 네트워크를 BrainScript 변수에 로드합니다.
2단계는 CloneFunction() 사용하여 로드된 네트워크에서 기능 추출 관련 섹션을 복제합니다. 이 섹션은 featExtNetwork.inputfeatExtNetwork.feat연결하는 하위 그래프입니다.
parameters="constant"지정했으므로 featExtNetwork.feat 사용하는 모든 매개 변수도 복제되고 읽기 전용으로 만들어집니다.
3단계와 4단계에서는 새 네트워크가 정의됩니다. 이는 다른 BrainScript 모델과 마찬가지로 수행되며, 이제는 featExt() 함수를 사용할 수 있습니다.
.
[ 및 ] 노드 이름 문제
. 또는 [ 또는 ]포함하는 네트워크의 노드를 참조하려면 해당 문자를 _대체합니다.
예를 들어 networkresult.z노드를 포함하는 경우 network.result.z 실패합니다. 대신 network.result_z.
예: 기존 네트워크의 노드 수정
기존 네트워크의 내부 부분을 수정하려면 실제로 네트워크를 복제하지만 수정은 복제 프로세스의 일부로 적용됩니다. 이 작업은 BS.Network.Edit()수행됩니다.
Edit() 네트워크의 모든 노드를 반복하고 각 노드를 호출자가 전달한 람다 함수에 하나씩 제공합니다. 그런 다음 이러한 람다 함수는 노드를 검사하고 수정되지 않은 노드를 반환하거나 그 자리에 새 노드를 반환할 수 있습니다.
Edit() 지정되지 않은 순서로 노드를 반복합니다. 대체 노드가 대체된 네트워크 노드를 참조하는 경우 Edit() 마지막 단계로 이러한 모든 참조를 해당 대체 항목(즉, "올바른 작업 수행")으로 업데이트합니다.
TODO: 예제입니다.
다음: 전체 함수 참조