본문 바로가기

TechTrend

Tensorflow.js 사용하기(Part.3)

TensorFlow.js 사용하기(Part.3)

 

 

  • Transfer Learning

이전 파트에서 우리는 밑바닥부터 모델을 학습시켜야했다.

이는 모델이 일정 수준에 이르기까지 많은 반복 학습이 요구되기 때문에 비용이 많이 든다.

따라서 이번에 mobilenet이라 불리는 미리 조금 학습된 모델을 사용한다.

mobilenet은 모바일에서 동작하도록 최적화되어 있으며

미리 가중치가 조금 세팅되어있는 CNN이다.

또한 ImageNet프로젝트에 나오는 1,000개의 클래스에 대한 이미지들로 학습되었다.

이제 모델을 로드해보자.

const mobilenet = await tf.loadLayersModel(
      'https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_0.25_224/model.json');

위와 같이 모델을 불러왔다면

모델의 데이터 입력, 출력 텐서의 형태를 점검해봐야한다.

(  loadModel( )가 버전업되면서 loadLayersModel( )로 대체되었습니다.  )

 

//The input size is [null, 224, 224, 3]
const input_s = mobilenet.inputs[0].shape;

//The output size is [null, 1000]
const output_s = mobilenet.outputs[0].shape;

따라서 입력으로는 [1,224,224,3] 형태의 이미지가,

출력은 ImageNet으로 학습된 1000개의 분류를 가지고 있기 때문에

[1,1000]의 형태가 필요하다.

 

0행렬을 입력으로 주면 1,000개의 클래스 중에

무엇으로 분류해낼까?

한번 예측해보자.

var pred = mobilenet.predict(tf.zeros([1, 224, 224, 3]));
pred.argMax().print();

코드를 수행해보니 연(kite)을 뜻하는 21이 나왔다.

이처럼 잘 동작하는 것을 확인했다면

모델을 사용하기 위해서는

모델을 이루는 각 레이어와

그 구성을 확인해봐야한다.

//The number of layers in the model '88'
const len = mobilenet.layers.length;

//this outputs the name of the 3rd layer 'conv1_relu'
const name3 = mobilenet.layers[3].name;

보다시피 88개의 레이어를 또 다른 데이터로 다시 학습시킨다는 것은 정말 부담스럽다.

그래서 전부 다시 학습하지 않는 약간의 트릭이 있다.

바로 1,000개의 클래스가 아닌

원하는 수의 클래스로 출력될 dense layer를

새로 만들어 붙이는 것이다.

 

예를 들면, 당근과 오이를 분류할 때

mobilenet 모델에서 임의의 레이어를 선택하여

선택된 레이어부터 그 뒷부분을 잘라내고

출력 사이즈가 2(당근, 오이)인

dense layer를 새로 만들어

학습시킨 뒤 이어 붙이면 된다.

 

따라서 mobilenet이 의미하는 바는

'일정 수준의 학습이 완료된 상태'를

유지하는 모델이라는 것이다.

따라서 우리는 dense layer만 학습시키면 된다.

 

먼저, mobilenet모델에서 기존의 dense layer 부분을 제거해야한다.

81번째 conv_pw_13_relu이라는 레이어를 임의로 추출해보자.

const layer = mobilenet.getLayer('conv_pw_13_relu');

이제 해당 레이어가 출력레이어가 되도록 mobilenet을 갱신하자.

mobilenet = tf.model({inputs: mobilenet.inputs, outputs: layer.output});

마지막으로 훈련가능한 새로운 모델을 만들자.

새로운 모델의 입력 형태를 정의하기 위해서는

갱신된 mobilenet의 마지막 출력 형태를 알아야 한다.

//this outputs a layer of size [null, 7, 7, 256]
const layerOutput = layer.output.shape;

위와 같이 출력형태를 확인 했다면

새로 만든 모델의 입력형태로 정의해주면 된다.

trainableModel = tf.sequential({
    layers: [
      tf.layers.flatten({inputShape: [7, 7, 256]}),
      tf.layers.dense({
        units: 100,
        activation: 'relu',
        kernelInitializer: 'varianceScaling',
        useBias: true
      }),
      tf.layers.dense({
        units: 2,
        kernelInitializer: 'varianceScaling',
        useBias: false,
        activation: 'softmax'
      })
    ]
  });

보다시피 100개의 뉴런을 가지는 dense layer와

출력 사이즈가 2인 dense layer를 새로운 모델로 구성했다.

const activation = mobilenet.predict(input);
const predictions = trainableModel.predict(activation);

코드를 보면 갱신된 mobilenet의 출력을

activation이라는 변수로 받은 뒤

새로 만든 모델의 입력으로 주어

최종추론결과를 predictions라는 변수로 받았다.

 

그리고 이전 파트에서 했던 것과 같이

새로 만든 모델은 최적화기를 통해

학습시키면 된다.

 

이렇게 전이 학습까지 텐서플로우의 기본적인 사용법을 알아보았다.

인공지능 이론에 대한 기초를 다루는 것이 아니다 보니

그에 사용되는 많은 이론들을 생략하였다.

 

자바스크립트를 좋아하는 개발자로서 웹 시장에서의 AI가

빨리 발전했으면 하는 마음에 포스팅하였다.

 

다만, 아쉬운 점은 The TensorFlow Blog에 기재된 글이

오래되어 버전과 맞지 않는 API들이 있다.

하지만 포스팅 전에 미리 테스트를 거쳤다.

(21.01.15)

 

 

 

감사합니다. : )