전송 Learning 사용하여 고유한 이미지 분류자 빌드

목차

요약

imageimageimageimage

위의 이미지는 이 자습서의 두 번째 부분에서 사용되는 테스트 이미지입니다. 이 작업은 기존 분류자 모델인 기본 모델을 수정하여 다양한 범주의 이미지(양과 늑대 예제)를 구분할 수 있는 분류자를 학습시키는 것입니다. 여기서는 ImageNet 모음에서 학습된 ResNet_18 모델을 사용합니다. 몇 초 만에 클래스당 15개의 이미지만 학습하고 10개의 테스트 이미지를 모두 올바르게 예측 합니다(몇 가지 솔트 곡물 참고).

다음은 전이 학습 자습서의 주요 리소스입니다.

레시피 TransferLearning.pyTransferLearning_Extended.py ( Examples/Image/TransferLearning 참조).
미리 학습된 모델 전이 학습을 위한 기본 모델로 미리 학습된 ResNet_18 모델을 사용합니다.
데이터 102개의 범주와 양과 늑대의 예제 이미지가 있는 꽃 데이터 집합(설정 참조).
실행 방법 아래 설명을 따릅니다.

설치 프로그램

이 예제에서 코드를 실행하려면 CNTK Python 환경이 필요합니다(설치 도움말은 여기 참조).

필요한 데이터와 미리 학습된 모델을 다운로드하려면 다음 명령을 실행하여 Examples/Image/TransferLearning 폴더를 만듭니다.

python install_data_and_model.py

예제 실행

imageimageimageimage

이 섹션에서는 Flowers 데이터 집합에 대한 분류자를 빌드합니다. 데이터 세트는 이미지 분류 작업을 위해 옥스포드 대학의 시각적 기하 도형 그룹에 의해 만들어졌습니다. 그것은 영국에 공통 꽃의 102 다른 범주로 구성하고 한 번 6000 두 번 1000 이미지의 세 세트로 분할 약 8000 이미지를 포함. 자세한 내용은 VGG 홈페이지를 참조하세요.

Flowers 데이터 집합 실행에서 전송 학습 모델을 학습하고 평가하려면

python TransferLearning.py

이 모델은 20 Epoch에 대한 학습 후 Flowers 데이터 집합에서 93%의 정확도를 달성합니다.

전이 학습의 기본 개념

전송 학습에 기본 모델을 사용하는 경우 기본적으로 기본 모델을 학습하는 동안 학습된 기능과 개념을 기반으로 합니다. ResNet_18 나선형 DNN의 경우 이는 예를 들어 원래 기본 모델의 클래스 레이블을 예측하는 최종 조밀 계층을 차단 하고 새 작업의 클래스 레이블을 예측하는 새 조밀한 계층으로 대체한다는 것을 의미합니다. 이전 및 새 예측 계층에 대한 입력은 동일합니다. 학습된 기능을 재사용하기만 하면 됩니다. 그런 다음, 새 예측 계층의 새 가중치 또는 전체 네트워크의 모든 가중치 중 하나만 수정된 네트워크를 학습시킵니다.

다음 코드는 기본 모델에서 새 모델을 만드는 부분입니다 TransferLearning.py .

    # Load the pretrained classification net and find nodes
    base_model   = load_model(base_model_file)
    feature_node = find_by_name(base_model, feature_node_name)
    last_node    = find_by_name(base_model, last_hidden_node_name)

    # Clone the desired layers with fixed weights
    cloned_layers = combine([last_node.owner]).clone(
        CloneMethod.freeze if freeze else CloneMethod.clone,
        {feature_node: Placeholder(name='features')})

    # Add new dense layer for class prediction
    feat_norm  = input_features - Constant(114)
    cloned_out = cloned_layers(feat_norm)
    z          = Dense(num_classes, activation=None, name=new_output_node_name) (cloned_out)

사용자 고유의 사용자 지정 이미지 분류자 빌드

이전 섹션에서는 학습을 위해 약 6,000개의 이미지를 사용하여 102개의 다양한 꽃 범주를 구분하는 분류자를 학습시켰습니다. 이 섹션에서는 범주당 15개 이미지만 사용하여 양에게서 늑대에게 알릴 수 있는 분류자를 빌드합니다. 전이 학습에 동일한 ResNet_18 기본 모델을 사용합니다. 모델 실행을 학습하고 평가하려면

python TransferLearning_Extended.py

이 모델은 각각 양과 늑대의 5개 이미지에서 테스트되며 모든 레이블을 올바르게 예측합니다. 출력 파일에는 예측 결과의 JSON 표현이 줄당 포함됩니다.

[{"class": "Sheep", "predictions": {"Sheep":1.000, "Wolf":0.000}, "image": "..."}]
[{"class": "Sheep", "predictions": {"Sheep":1.000, "Wolf":0.000}, "image": "..."}]
[{"class": "Sheep", "predictions": {"Sheep":1.000, "Wolf":0.000}, "image": "..."}]
[{"class": "Sheep", "predictions": {"Sheep":0.997, "Wolf":0.003}, "image": "..."}]
[{"class": "Sheep", "predictions": {"Sheep":1.000, "Wolf":0.000}, "image": "..."}]
[{"class": "Wolf", "predictions": {"Wolf":1.000, "Sheep":0.000}, "image": "..."}]
[{"class": "Wolf", "predictions": {"Wolf":1.000, "Sheep":0.000}, "image": "..."}]
[{"class": "Wolf", "predictions": {"Wolf":1.000, "Sheep":0.000}, "image": "..."}]
[{"class": "Wolf", "predictions": {"Wolf":1.000, "Sheep":0.000}, "image": "..."}]
[{"class": "Wolf", "predictions": {"Wolf":1.000, "Sheep":0.000}, "image": "..."}]
[{"class": "unknown", "predictions": {"Sheep":0.994, "Wolf":0.006}, "image": "..."}]
[{"class": "unknown", "predictions": {"Sheep":0.614, "Wolf":0.386}, "image": "..."}]
[{"class": "unknown", "predictions": {"Wolf":0.980, "Sheep":0.020}, "image": "..."}]

마지막 세 개의 이미지에는 기본 진리 클래스가 할당되어 있지 않습니다. 이는 물론 웹 서비스에서 보이지 않는 이미지의 채점과 같은 유효한 시나리오입니다. 실제 이미지는 아래에 표시된 세 개의 새 이미지입니다. JSON 출력에서 이러한 클래스에 대한 기본 진리 클래스는 .로 unknown설정됩니다. 분류자가 학습된 개념에 대한 예측은 몇 가지 학습 이미지에도 불구하고 매우 좋습니다. 이는 미리 학습된 기본 모델로 인해 큰 부분에 있습니다. 분류자가 양과 늑대만 알고 있기 때문에 보이지 않는 개념(예: 새의 이미지)에 대한 예측은 물론 그다지 의미가 없습니다. 이에 대한 자세한 내용은 나중에 참조하세요.

imageimageimage

사용자 지정 이미지 집합의 폴더 구조

사용자 고유의 이미지와 함께 스크립트를 TransferLearning_Extended.py 사용할 수 있습니다. 필요한 항목은 다음과 같습니다.

  1. class_mapping - 범주의 이름을 포함하는 배열(예: ['wolf', 'sheep']
  2. train_map_file- 줄당 먼저 이미지 URL과 탭을 포함하는 텍스트 파일은 해당 범주 인덱스(예: 늑대 또는 1 양용)를 구분합니다. 0
  3. test_map_file - 해당 범주에 맵 테스트 이미지를 매핑하는 텍스트 파일입니다. 테스트 이미지에서 알 수 없는 범주의 경우 범주 인덱스로 사용합니다 -1 .

스크립트는 다음과 같은 방식으로 이미지를 구성하는 경우 위의 세 항목을 모두 생성할 수 있습니다.

<image root folder>
    Train
        Sheep
        Wolf
    Test
        Sheep
        Wolf
        <optional: image files with unknown label directly here>

<cntk root>/Examples/Image/DataSets/Animals/ 예를 참조하세요. 폴더의 Train 각 하위 폴더는 하나의 범주(단일 수준만, 재귀 없음)로 간주됩니다. 루트 폴더의 개별 이미지 학습의 Train 경우 할당된 범주가 없으므로 무시됩니다. 폴더에서 발생하지 Train 않는 폴더의 Test 추가 하위 폴더는 무시됩니다. 분류되지 않은 개별 이미지를 테스트하는 경우 점수 매기기에도 사용됩니다. 즉, 예제의 세 개의 새 이미지와 같이 폴더에 Test 직접 저장된 이미지도 사용됩니다.

사용자 지정 이미지 폴더를 사용하려면 스크립트의 맨 위에 TransferLearning_Extended.py 설정 test_image_foldertrain_image_folder 해야 합니다.

# define data location and characteristics
train_image_folder = "<your_image_root_folder>/Train"
test_image_folder = "<your_image_root_folder>/Test"

그런 다음, 간단히 실행 python TransferLearning_Extended.py합니다. 다른 기본 모델을 사용하는 방법은 아래에 설명되어 있습니다.

점수 매기기를 위해 test_map_file단일 이미지를 하나씩 채점하려는 경우와 같이 사용할 필요가 없습니다. 학습된 전송 학습 모델을 한 번 로드한 다음 새 이미지에 대한 예측을 가져올 때마다 호출 eval_single_image 하기만 하면 됩니다.

    # once:
    # load the trained transfer learning model
    trained_model = load_model(new_model_file)

    # for every new image:
    # get predictions for a single image
    probs = eval_single_image(trained_model, img_file, image_width, image_height)

소금 몇 가지 곡물

학습 이미지는 나중에 점수를 매기려는 시나리오를 충분히 다루어야 합니다. 분류자가 완전히 새로운 개념이나 컨텍스트를 볼 경우 성능이 좋지 않습니다. 몇 가지 예만 있습니다.

  • 제약 조건 환경(예: 실내)의 이미지에 대해서만 학습하고 다른 환경(실외)에서 이미지의 점수를 매기려고 합니다.
  • 특정 메이크 이미지에 대해서만 학습하고 다른 사람의 점수를 매기려고 합니다.
  • 테스트 이미지는 조명, 배경, 색, 크기, 위치 등과 같은 특징이 크게 다릅니다.
  • 테스트 이미지에는 완전히 새로운 개념이 포함되어 있습니다.

catch-all 범주를 추가하는 것이 좋지만 해당 범주에 대한 학습 데이터에 점수 매기기 시 예상되는 이미지와 충분히 유사한 이미지가 포함된 경우에만 좋습니다. 위의 예제와 같이 양과 늑대의 이미지를 사용하여 분류자를 학습시키고 새 이미지의 점수를 매기는 데 사용하는 경우 분류자는 다른 범주를 모르기 때문에 여전히 양이나 늑대 레이블만 할당할 수 있습니다. catch-all 범주를 추가하고 조류의 학습 이미지를 추가하려는 경우 분류자는 새 이미지에 대해 클래스를 올바르게 예측할 수 있습니다. 그러나, 우리가 그것을 제시하는 경우, 예를 들어, 자동차의 이미지, 그것은 단지 양, 늑대와 새를 알고 이전과 같은 문제에 직면 (우리는 단지 캐치 올이라고 호출 일어났다). 따라서 학습 데이터도 catch-all을 위해 나중에 채점할 때 예상되는 개념과 이미지를 충분히 포함해야 합니다.

유의해야 할 또 다른 측면은 특정 기본 모델이 일부 전송 학습 작업에는 매우 잘 작동할 수 있고 다른 사람들에게는 좋지 않을 수 있다는 것입니다. 예를 들어 위의 ResNet_18 모델은 동물, 사람, 자동차 및 기타 매일 개체의 많은 이미지를 포함하는 ImageNet 모음에 미리 학습되었습니다. 전송 학습에서 이 기본 모델을 사용하여 유사한 매일 개체 에 대한 분류자를 빌드하면 잘 작동할 수 있습니다. 기본 모델과 동일한 모델을 사용하여 미생물 또는 연필 드로잉 이미지에 대한 분류자를 작성하면 평범한 결과만 생성할 수 있습니다.

다른 기본 모델 사용

다른 모델을 기본 모델로 사용하려면 다음 매개 변수 TransferLearning.py 를 다음과 같이 조정해야 합니다(예: TransferLearning_Extended.py).

# define base model location and characteristics
_base_model_file = os.path.join(base_folder, "..", "..", "..", "PretrainedModels", "ResNet_18.model")
_feature_node_name = "features"
_last_hidden_node_name = "z.x"
_image_height = 224
_image_width = 224
_num_channels = 3

모델에 있는 노드 이름과 선택할 last_hidden_node 노드를 조사하려면 다음 줄을 사용하여 모든 노드 이름 및 노드 셰이프를 인쇄할 수 있습니다(방법 TransferLearning.py참조__main__).

    # You can use the following to inspect the base model and determine the desired node names
    node_outputs = get_node_outputs(load_model(_base_model_file))
    for out in node_outputs: print("{0} {1}".format(out.name, out.shape))