인프런 커뮤니티 질문&답변

유영재님의 프로필 이미지
유영재

작성한 질문수

딥러닝 CNN 완벽 가이드 - Fundamental 편

여러 가지 부분에서 질문이 있습니다

작성

·

160

0

안녕하세요. 여러 궁금한 점이 있어서 질문이 있습니다

1. augmentation 없이 acc, val_acc가 0.99, 0.98이 되는데, 여기서 더 성능을 끌어 올리기 위해서 aug가 대안이 되긴하나요?  aug가 val_acc면에서 0.98에서 0.99로  올릴 수 있는 해결책이 될까요?

2. fine-tuning 시 2단계에서 layer trainable을 다 안하고, 어느 일부분만 하고 싶다면 이를 module 단위로 나누는게 맞을까요? 그러면 복잡한 모델 같은 경우에는 직접 중간 모듈 시작 번호를 알아서 layer[-21:] = Trainable 이런식으로 해야겠네요?

3. 딥러닝에서 어떤 예측값을 뽑아낼 때 StratifiedKFold로 해서 마지막에 나누기를 해서 결과로 도출하는 것은 어떻게 생각하시나요? https://www.kaggle.com/c/invasive-species-monitoring 이 대회는 이진분류이긴 한데, 꽤나 성능이 좋게 나왔습니다

4. batch-norm을 적용한다면 모든 conv - acti 사이에 한 번씩 적용해야 하는 것인가요? 아니면 텀을 두고 batch-norm을 적용해도 되는 것인가요?

답변 3

0

유영재님의 프로필 이미지
유영재
질문자

제가 어디다가 감사인사를 남겨야할지 모르겠지만, 선생님 강의 한 번 쑥 듣고 프로그래머스에서 하는 머신러닝 챌린지 (이미지 분류)에 참가해서 10등이라는 성과를 거뒀습니다. 정말 감사드립니다. 혼자 공부하다보니 이후에도 많이 질문좀 드리겠습니다

권 철민님의 프로필 이미지
권 철민
지식공유자

오, 대단하시군요.

꾸준히 노력하시더니, 결국 좋은 성적으로 이어지셨군요.

저도 뿌듯합니다.

0

유영재님의 프로필 이미지
유영재
질문자

1. 감사합니다. 생각해보니 데이터가 많지 않은 val_acc가 정답이 될 수는 없겠네요

2. 먼저 FC 레이어 학습 후 fine_tuning 시 모든 레이어를 trainable로 하는 것이 아니라 뒤에 몇개 레이어만 True로 바꾸려고 할 때는 반드시 블록 단위로 잘라서 해야 하는 것이죠? VGG 같은 경우에는 conv-conv-conv-maxpool을 하나의 블록으로 말한 것입니다. 그런데 efficient나 이런 것들은 깊이 잘 모르고 처음보다 보니 어디서 짤라야 할지 애매해서요

3. 코드를 첨부하겠습니다. 다음과 같이 StratifiedKFold로 데이터를 섞다 보니 캐글같은 대회에서 성능이 좋게 나오네요. 물론 하나의 대회에서 제가 시도해본 것이라 점수를 올리는 전형적인 방법인지는 모르겠습니다

skf = StratifiedKFold(n_splits=5)
n_iter= 0

for train_index, test_index in skf.split(train, train['invasive']):
    n_iter += 1
    label_train= train['invasive'].iloc[train_index]
    label_test= train['invasive'].iloc[test_index]
    print('## 교차 검증: {0}'.format(n_iter))
    print('학습 레이블 데이터 분포:\n', label_train.value_counts())
    print('검증 레이블 데이터 분포:\n', label_test.value_counts())
    
    x_train = train.iloc[train_index]
    x_valid = train.iloc[test_index]
    
    idg = ImageDataGenerator(horizontal_flip=True,
                         preprocessing_function=preprocess_input)

    idg2 = ImageDataGenerator(preprocessing_function=preprocess_input)
    # 사이즈가 늘어남에 따라 batch_size는 줄어들어야 한다
    # 라벨이 정수형이라서 categorical 오류. 그래서 class_mode를 바꾸거나 y_col의 자료형을 바꿔준다
    train_generator = idg.flow_from_dataframe(x_train, 
                                              x_col='name', 
                                              y_col='invasive',
                                              target_size=(300, 300),
                                              batch_size=32)

    validation_generator = idg2.flow_from_dataframe(x_valid,
                                                    x_col='name',
                                                    y_col='invasive',
                                                    target_size=(300, 300),
                                                    batch_size=32,
                                                    shuffle=False)
    
    model = Sequential()

    model.add(EfficientNetB0(weights='imagenet', include_top=False, pooling='avg'))
    model.add(Dropout(0.5))
    model.add(Dense(512, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(128, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(2, activation='softmax'))
    
    # model.summary()
    
    mcp = ModelCheckpoint('save_best_model.hdf5', save_best_only=True, monitor='val_loss', verbose=1)
    rlr = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=5, verbose=1)
    els = EarlyStopping(monitor='val_loss', patience=7, verbose=1)

    model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
    
    history = model.fit(train_generator,
                      steps_per_epoch=len(train_generator),
                      validation_data=validation_generator,
                      validation_steps=len(validation_generator),
                      epochs=50,
                      callbacks=[mcp, rlr, els])
    
    model2 = load_model('./save_best_model.hdf5')
    
    model2.evaluate(validation_generator)                                               
    
    pred = model2.predict(test_generator, verbose=1)
    
    preds += pred[:,1]
권 철민님의 프로필 이미지
권 철민
지식공유자

2. 먼저 FC 레이어 학습 후 fine_tuning 시 모든 레이어를 trainable로 하는 것이 아니라 뒤에 몇개 레이어만 True로 바꾸려고 할 때는 반드시 블록 단위로 잘라서 해야 하는 것이죠? VGG 같은 경우에는 conv-conv-conv-maxpool을 하나의 블록으로 말한 것입니다. 그런데 efficient나 이런 것들은 깊이 잘 모르고 처음보다 보니 어디서 짤라야 할지 애매해서요

=> 기본적으로 Fine Tuning은 Pretrained 모델을 활용할 때 적용하며, Pretrained 모델의 Feature extractor 부분의 weight가 급격히 변하는 것을 방지하기 위해서 일차적으로 Feature Extractor 부분을 freeze하고 Classification layer만 어느정도 먼저 학습 하는 것입니다.

모델의 특정 부분, 또는 특정 block 레벨로만 Freeze하는 경우도 있습니다. 하지만 이걸 어떤 부분을 freeze해야 하는지는 명확하지 않습니다. efficientnet의 fine tuning 예제를 보면, 가끔 특정 block 레벨로만 freeze하는데, 그 이유에 대해서는 명확히 기술되어 있지 않습니다. 

권장은 Feature Extractor 부분 전체를 freeze하는 방법입니다.

3. 코드를 첨부하겠습니다. 다음과 같이 StratifiedKFold로 데이터를 섞다 보니 캐글같은 대회에서 성능이 좋게 나오네요. 물론 하나의 대회에서 제가 시도해본 것이라 점수를 올리는 전형적인 방법인지는 모르겠습니다

=> 네, 보통 Kaggle 같은 competition에서는 KFold 방식으로 모델을 각각 학습 시키고, predict 결과를 평균해서 submit하여 성능을 향상시킵니다.

0

권 철민님의 프로필 이미지
권 철민
지식공유자

안녕하십니까,

1. augmentation 없이 acc, val_acc가 0.99, 0.98이 되는데, 여기서 더 성능을 끌어 올리기 위해서 aug가 대안이 되긴하나요?  aug가 val_acc면에서 0.98에서 0.99로  올릴 수 있는 해결책이 될까요?

=> 물론입니다. augmentation을 적용해 주는게 성능을 올리는데 도움이 됩니다. 다만 왜 validation 성능에 너무 집착하지 않으셨으면 합니다. validation 데이터는 일반적으로 적기 때문에 validation 성능이 좋다고 반드시 모델 성능이 좋은 것은 아닙니다.

2. fine-tuning 시 2단계에서 layer trainable을 다 안하고, 어느 일부분만 하고 싶다면 이를 module 단위로 나누는게 맞을까요? 그러면 복잡한 모델 같은 경우에는 직접 중간 모듈 시작 번호를 알아서 layer[-21:] = Trainable 이런식으로 해야겠네요?

=> 모듈단위라는게 어떤걸 의미하시는지요? 자세히 기술 부탁드립니다.

어찌되었든, 해당 layer 번호를 찾아서 freeze/unfreeze 시키시면  됩니다.

3. 딥러닝에서 어떤 예측값을 뽑아낼 때 StratifiedKFold로 해서 마지막에 나누기를 해서 결과로 도출하는 것은 어떻게 생각하시나요? https://www.kaggle.com/c/invasive-species-monitoring 이 대회는 이진분류이긴 한데, 꽤나 성능이 좋게 나왔습니다

=> 음,, 어떤 내용인지 제가 알수가 없군요. 해당 URL로 가봐도, 어디서 찾아봐야 할지도 모르겠습니다. 이 질문으로는 제가 답변을 드릴 수가 없군요.

4. batch-norm을 적용한다면 모든 conv - acti 사이에 한 번씩 적용해야 하는 것인가요? 아니면 텀을 두고 batch-norm을 적용해도 되는 것인가요?

=> 정해진 규칙은 없지만, 일반적으로 conv - acti 사이에 한번씩 적용합니다.

유영재님의 프로필 이미지
유영재

작성한 질문수

질문하기