2020.09.07

TensorFlow.js로 브라우저에서 텐서플로우를 사용하는 방법

Martin Heller | InfoWorld
텐서플로우를 사용하면 비교적 적은 양의 학습 데이터로 간단한 신경망을 학습시킬 수 있지만, 대용량 학습 데이터 집합을 사용한 심층 신경망의 경우 가속을 위해 CUDA를 지원하는 엔비디아 GPU, 또는 구글 TPU나 FPGA를 사용하는 것이 거의 필수적이다. 최근까지 그 대안은 CPU 클러스터에서 몇 주에 걸쳐 학습시키는 방법뿐이었다.

이런 가운데 텐서플로우 2.0의 혁신 중 하나가 바로 자바스크립트 구현인 TensorFlow.js다. 필자는 이것이 학습이나 추론 속도를 개선할 것으로 기대하지 않았는데, 웹GL(WebGL) API를 통해 모든 GPU(CUDA GPU뿐만 아니라)를 지원해 실제로 속도 개선 효과가 있다.
 

TensorFlow.js란?

TensorFlow.js는 자바스크립트로 머신 러닝 모델을 개발 및 학습시키고 브라우저나 Node.js에 배포하는 라이브러리다. 기존 모델을 사용하고 파이썬 텐서플로우 모델을 변환하고 전이 학습을 사용해 자체 데이터로 기존 모델을 재학습시키고 처음부터 새로 모델을 개발할 수 있다.
 

TensorFlow.js 백엔드

TensorFlow.js는 여러 백엔드를 지원하지만 활성화는 한 번에 하나만 가능하다. TensorFlow.js Node.js 환경은 설치된 파이썬/C 텐서플로우 빌드를 백엔드로 사용하도록 지원하며, 이를 통해 예를 들어 CUDA와 같은 해당 시스템의 가용 하드웨어 가속을 사용할 수 있다. Node.js용 자바스크립트 기반 백엔드도 있지만 기능은 제한적이다.

브라우저에서 TensorFlow.js에는 서로 다른 특성의 여러 백엔드가 있다. 웹GL 백엔드는 저장용으로 웹GL 텍스처를, 실행용으로 웹GL 셰이더를 사용해 GPU를 지원하며, 일반 CPU 백엔드에 비해 최대 100배 더 빠른 실행이 가능하다. 웹GL에는 CUDA가 불필요하므로 현재 있는 GPU가 무엇이든 활용할 수 있다.

브라우저용 웹어셈블리(WASM) TensorFlow.js back 백엔드는 신경망 연산자의 최적화된 CPU 구현을 위해 XNNPACK 라이브러리를 사용한다. WASM 백엔드는 일반적으로 자바스크립트 CPU 백엔드에 비해 훨씬 더 빠르지만(10~30배) 모델이 아주 작은 경우를 제외하면 웹GL 백엔드보다는 대체로 느리다. 각자의 상황마다 다를 수 있으므로 현재의 하드웨어에서 자신의 모델을 사용해 WASM과 웹GL 백엔드를 모두 테스트하는 것이 좋다.
 

TensorFlow.js 모델과 레이어

TensorFlow.js는 신경망 모델 구축에 두 가지 API를 지원한다. 하나는 레이어(Layers) API로, 사실상 텐서플로우 2의 케라스(Keras) API와 동일하다. 다른 하나는 텐서를 직접적으로 조작하는 코어(Core) API다. 케라스와 마찬가지로 TensorFlow.js 레이어 API 역시 순차적 방법과 함수적 방법, 두 가지 방법으로 모델을 만들 수 있다. 순차적 API는 선형적인 레이어 스택으로, 레이어 목록 또는 model.add() 메소드를 사용해 구현한다.
 
const model = tf.sequential({
   layers: [
      tf.layers.dense({inputShape: [784], units: 32, activation: 'relu'}),
      tf.layers.dense({units: 10, activation: 'softmax'}),
   ]
});

함수적 API는 tf.model() API를 사용하며 임의 DAG(유향 비순환 그래프) 네트워크를 만들 수 있다.
 
// Create an arbitrary graph of layers, by connecting them
// via the apply() method.
const input = tf.input({shape: [784]});
const dense1 = tf.layers.dense({units: 32, activation: 'relu'}).apply(input);
const dense2 = tf.layers.dense({units: 10, activation: 'softmax'}).apply(dense1);
const model = tf.model({inputs: input, outputs: dense2});

코어 API는 다른 코드를 사용해서 같은 결과를 달성할 수 있으며 레이어에 대한 직관적인 연계성은 더 적다. 다음 모델은 기본적인 텐서 연산처럼 보이지만 앞의 두 공식과 같은 신경망을 생성한다. relu()softmax()를 사용한 부분에 주목할 필요가 있다. 둘 다 아래 model() 함수의 신경망 연산이다.
 
// The weights and biases for the two dense layers.
const w1 = tf.variable(tf.randomNormal([784, 32]));
const b1 = tf.variable(tf.randomNormal([32]));
const w2 = tf.variable(tf.randomNormal([32, 10]));
const b2 = tf.variable(tf.randomNormal([10]));

function model(x) {
   return x.matMul(w1).add(b1).relu().matMul(w2).add(b2).softmax();
}
 

사전 제작된 TensorFlow.js 모델

사전 제작된 십여 가지의 TensorFlow.js 모델이 문서화돼 리포지토리에 제공되며 NPM(Node.js에서 사용하는 경우)과 unpkg(브라우저에서 사용하는 경우)에 호스팅된다. 이 모델을 그대로 사용하거나 전이 학습에 사용할 수 있다. 조금만 작업하면 다른 모델을 위한 구성 요소로 사용할 수도 있다. 이 중 여러 모델이 디바이스의 카메라를 실시간으로 사용한다
 
핸드포즈(handpose)는 손가락과 손바닥을 인식한다. © IDG

다음 목록은 대부분의 사전 패키징된 TensorFlow.js 모델로 연결되는 색인이다.
   

ml5.js란?

ml5.js는 TensorFlow.js에 대한 친화적인 고수준의 오픈소스 인터페이스로, 주로 NYU에서 개발했다. ml5.js를 이용하면 자세 감지, 텍스트 생성, 이미지 스타일링, 작곡, 피치 검출, 일반적인 영어 단어 관계를 비롯한 다양한 용도의 사전 학습된 모델을 브라우저에서 즉각 액세스할 수 있다. TensorFlow.js의 주 대상이 데이터 과학자와 개발자라면 ml5.js는 머신 러닝에 대한 더 폭넓은 대중의 이해를 이끌고 윤리적 컴퓨팅, 책임감 있는 데이터 수집, 기술과 예술에서의 접근성과 사람 및 관점의 다양성을 촉진하는 데 목적을 둔다.

ml5.js의 예제는 대부분 TensorFlow.js 모델에 의존한다. 웹 페이지로 패키징되어 제공되므로 있는 그대로 실행하거나 편집(예를 들어 다른 이미지를 사용하도록)할 수 있다.
 
포즈넷을 이용하면 브라우저에서 이미지 혹은 동영상으로부터 실시간 자세 추정 작업을 할 수 있다. © IDG
 

데모: TensorFlow.js를 사용한 붓꽃 분류

1936년 R.A. 피셔가 선형 판별 분석을 설명하기 위해 고안한 유명한 붓꽃 구별 데이터 집합은 통계 및 머신 러닝 분류 방법의 테스트 사례로 널리 사용된다. 각 붓꽃 종의 샘플을 50개씩 사용해 길이, 너비, 꽃받침과 꽃잎 등 4가지 특징으로 붓꽃의 3가지 종을 분류한다. 피셔의 첫 논문은 인류유전학 전보에 게재됐는데, 이는 1936년 당시 이 논문이 데이터나 통계보다는 과학에 더 가까웠음을 보여준다.

이 데이터에 대해 군집 분석을 수행하면 두 가지 종이 하나의 군집을 공유하고, 세 번째(I. Setosa)가 별도의 군집을 형성한다. 반면 주성분 분석에서는 세 가지 종을 매우 정확히 구분할 수 있다. 다음 코드 발췌 부분에서 볼 수 있듯이 TensorFlow.js 샘플은 두 개의 완전히 연결된(밀집) 신경망 레이어를 가진 붓꽃 데이터에 부합한다.
 
// Define the topology of the model: two dense layers.
const model = tf.sequential();
model.add(tf.layers.dense(
   {units: 10, activation: 'sigmoid', inputShape: [xTrain.shape[1]]}
   ));
model.add(tf.layers.dense({units: 3, activation: 'softmax'}));
model.summary();

const optimizer = tf.train.adam(params.learningRate);
model.compile({
   optimizer: optimizer,
   loss: 'categoricalCrossentropy',
   metrics: ['accuracy'],
});

아래 화면에서 볼 수 있듯 이 모델은 3가지 종을 꽤 정확히 구분한다. 그러나 매개변수를 만지다 보면 40에포크 이상 반복 시 두 가지종(동일한 군집 내) 사이의 일부 혼동이 다시 나타나는 것을 발견할 수 있다.
 
2단계 레이어 신경망 모델을 이용한 붓꽃 데이터셋 모델 학습 © IDG
 

파이썬 텐서플로우 모델을 자바스크립트로 변환하기

TensorFlow.js 리포지토리의 일부에는 저장된 텐서플로우 및 케라스 모델에 대한 컨버터가 포함돼 있다. SavedModel(텐서플로우 기본값), HDF5(케라스 기본값), 텐서플로우 허브 등 3가지 형식을 지원한다. 표준 리포지토리의 저장된 모델, 직접 학습시킨 모델, 그리고 다른 곳에서 찾은 모델에 컨버터를 사용할 수 있다.

변환 과정은 2단계로 구성된다. 첫 번째 단계에서 기존 모델을 model.json과 이진 가중치 파일로 변환하고, 두 번째 단계에서 API를 사용해 TensorFlow.js로 모델을 로드한다. 변환된 텐서플로우와 텐서플로우 허브 모델의 경우 tf.loadGraphModel, 변환된 케라스 모델의 경우 tf.loadLayersModel이다.
 

전이 학습 사용

TensorFlow.js는 텐서플로우와 사실상 같은 방식으로 전이 학습을 지원한다. 문서에는 모바일넷(MobileNet)을 자체 이미지 및 음성 명령 인식용으로 맞춤 설정하기 위한 예제를 제공한다. 기본적으로 각 코드랩에서 하는 일은 학습된 모델 위에 작은 맞춤 분류자를 추가하고 이를 학습시키는 것이다.

전반적으로 볼 때 TensorFlow.js는 텐서플로우가 할 수 있는 거의 모든 일을 할 수 있다. 그러나 TensorFlow.js의 대상 환경에는(게임용 GPU) 일반적으로 텐서플로우 딥 러닝 학습에 사용되는 대형 엔비디아 서버 GPU에 비해 활용 가능한 GPU 메모리가 많지 않으므로 브라우저에서 실행되도록 하기 위해서는 모델의 크기를 줄여야 할 수도 있다. 변환 유틸리티에서 이 작업을 어느 정도 처리하지만 수동으로 레이어를 제거하고 학습의 배치 크기를 줄여야 할 수 있다. editor@itworld.co.kr


2020.09.07

TensorFlow.js로 브라우저에서 텐서플로우를 사용하는 방법

Martin Heller | InfoWorld
텐서플로우를 사용하면 비교적 적은 양의 학습 데이터로 간단한 신경망을 학습시킬 수 있지만, 대용량 학습 데이터 집합을 사용한 심층 신경망의 경우 가속을 위해 CUDA를 지원하는 엔비디아 GPU, 또는 구글 TPU나 FPGA를 사용하는 것이 거의 필수적이다. 최근까지 그 대안은 CPU 클러스터에서 몇 주에 걸쳐 학습시키는 방법뿐이었다.

이런 가운데 텐서플로우 2.0의 혁신 중 하나가 바로 자바스크립트 구현인 TensorFlow.js다. 필자는 이것이 학습이나 추론 속도를 개선할 것으로 기대하지 않았는데, 웹GL(WebGL) API를 통해 모든 GPU(CUDA GPU뿐만 아니라)를 지원해 실제로 속도 개선 효과가 있다.
 

TensorFlow.js란?

TensorFlow.js는 자바스크립트로 머신 러닝 모델을 개발 및 학습시키고 브라우저나 Node.js에 배포하는 라이브러리다. 기존 모델을 사용하고 파이썬 텐서플로우 모델을 변환하고 전이 학습을 사용해 자체 데이터로 기존 모델을 재학습시키고 처음부터 새로 모델을 개발할 수 있다.
 

TensorFlow.js 백엔드

TensorFlow.js는 여러 백엔드를 지원하지만 활성화는 한 번에 하나만 가능하다. TensorFlow.js Node.js 환경은 설치된 파이썬/C 텐서플로우 빌드를 백엔드로 사용하도록 지원하며, 이를 통해 예를 들어 CUDA와 같은 해당 시스템의 가용 하드웨어 가속을 사용할 수 있다. Node.js용 자바스크립트 기반 백엔드도 있지만 기능은 제한적이다.

브라우저에서 TensorFlow.js에는 서로 다른 특성의 여러 백엔드가 있다. 웹GL 백엔드는 저장용으로 웹GL 텍스처를, 실행용으로 웹GL 셰이더를 사용해 GPU를 지원하며, 일반 CPU 백엔드에 비해 최대 100배 더 빠른 실행이 가능하다. 웹GL에는 CUDA가 불필요하므로 현재 있는 GPU가 무엇이든 활용할 수 있다.

브라우저용 웹어셈블리(WASM) TensorFlow.js back 백엔드는 신경망 연산자의 최적화된 CPU 구현을 위해 XNNPACK 라이브러리를 사용한다. WASM 백엔드는 일반적으로 자바스크립트 CPU 백엔드에 비해 훨씬 더 빠르지만(10~30배) 모델이 아주 작은 경우를 제외하면 웹GL 백엔드보다는 대체로 느리다. 각자의 상황마다 다를 수 있으므로 현재의 하드웨어에서 자신의 모델을 사용해 WASM과 웹GL 백엔드를 모두 테스트하는 것이 좋다.
 

TensorFlow.js 모델과 레이어

TensorFlow.js는 신경망 모델 구축에 두 가지 API를 지원한다. 하나는 레이어(Layers) API로, 사실상 텐서플로우 2의 케라스(Keras) API와 동일하다. 다른 하나는 텐서를 직접적으로 조작하는 코어(Core) API다. 케라스와 마찬가지로 TensorFlow.js 레이어 API 역시 순차적 방법과 함수적 방법, 두 가지 방법으로 모델을 만들 수 있다. 순차적 API는 선형적인 레이어 스택으로, 레이어 목록 또는 model.add() 메소드를 사용해 구현한다.
 
const model = tf.sequential({
   layers: [
      tf.layers.dense({inputShape: [784], units: 32, activation: 'relu'}),
      tf.layers.dense({units: 10, activation: 'softmax'}),
   ]
});

함수적 API는 tf.model() API를 사용하며 임의 DAG(유향 비순환 그래프) 네트워크를 만들 수 있다.
 
// Create an arbitrary graph of layers, by connecting them
// via the apply() method.
const input = tf.input({shape: [784]});
const dense1 = tf.layers.dense({units: 32, activation: 'relu'}).apply(input);
const dense2 = tf.layers.dense({units: 10, activation: 'softmax'}).apply(dense1);
const model = tf.model({inputs: input, outputs: dense2});

코어 API는 다른 코드를 사용해서 같은 결과를 달성할 수 있으며 레이어에 대한 직관적인 연계성은 더 적다. 다음 모델은 기본적인 텐서 연산처럼 보이지만 앞의 두 공식과 같은 신경망을 생성한다. relu()softmax()를 사용한 부분에 주목할 필요가 있다. 둘 다 아래 model() 함수의 신경망 연산이다.
 
// The weights and biases for the two dense layers.
const w1 = tf.variable(tf.randomNormal([784, 32]));
const b1 = tf.variable(tf.randomNormal([32]));
const w2 = tf.variable(tf.randomNormal([32, 10]));
const b2 = tf.variable(tf.randomNormal([10]));

function model(x) {
   return x.matMul(w1).add(b1).relu().matMul(w2).add(b2).softmax();
}
 

사전 제작된 TensorFlow.js 모델

사전 제작된 십여 가지의 TensorFlow.js 모델이 문서화돼 리포지토리에 제공되며 NPM(Node.js에서 사용하는 경우)과 unpkg(브라우저에서 사용하는 경우)에 호스팅된다. 이 모델을 그대로 사용하거나 전이 학습에 사용할 수 있다. 조금만 작업하면 다른 모델을 위한 구성 요소로 사용할 수도 있다. 이 중 여러 모델이 디바이스의 카메라를 실시간으로 사용한다
 
핸드포즈(handpose)는 손가락과 손바닥을 인식한다. © IDG

다음 목록은 대부분의 사전 패키징된 TensorFlow.js 모델로 연결되는 색인이다.
   

ml5.js란?

ml5.js는 TensorFlow.js에 대한 친화적인 고수준의 오픈소스 인터페이스로, 주로 NYU에서 개발했다. ml5.js를 이용하면 자세 감지, 텍스트 생성, 이미지 스타일링, 작곡, 피치 검출, 일반적인 영어 단어 관계를 비롯한 다양한 용도의 사전 학습된 모델을 브라우저에서 즉각 액세스할 수 있다. TensorFlow.js의 주 대상이 데이터 과학자와 개발자라면 ml5.js는 머신 러닝에 대한 더 폭넓은 대중의 이해를 이끌고 윤리적 컴퓨팅, 책임감 있는 데이터 수집, 기술과 예술에서의 접근성과 사람 및 관점의 다양성을 촉진하는 데 목적을 둔다.

ml5.js의 예제는 대부분 TensorFlow.js 모델에 의존한다. 웹 페이지로 패키징되어 제공되므로 있는 그대로 실행하거나 편집(예를 들어 다른 이미지를 사용하도록)할 수 있다.
 
포즈넷을 이용하면 브라우저에서 이미지 혹은 동영상으로부터 실시간 자세 추정 작업을 할 수 있다. © IDG
 

데모: TensorFlow.js를 사용한 붓꽃 분류

1936년 R.A. 피셔가 선형 판별 분석을 설명하기 위해 고안한 유명한 붓꽃 구별 데이터 집합은 통계 및 머신 러닝 분류 방법의 테스트 사례로 널리 사용된다. 각 붓꽃 종의 샘플을 50개씩 사용해 길이, 너비, 꽃받침과 꽃잎 등 4가지 특징으로 붓꽃의 3가지 종을 분류한다. 피셔의 첫 논문은 인류유전학 전보에 게재됐는데, 이는 1936년 당시 이 논문이 데이터나 통계보다는 과학에 더 가까웠음을 보여준다.

이 데이터에 대해 군집 분석을 수행하면 두 가지 종이 하나의 군집을 공유하고, 세 번째(I. Setosa)가 별도의 군집을 형성한다. 반면 주성분 분석에서는 세 가지 종을 매우 정확히 구분할 수 있다. 다음 코드 발췌 부분에서 볼 수 있듯이 TensorFlow.js 샘플은 두 개의 완전히 연결된(밀집) 신경망 레이어를 가진 붓꽃 데이터에 부합한다.
 
// Define the topology of the model: two dense layers.
const model = tf.sequential();
model.add(tf.layers.dense(
   {units: 10, activation: 'sigmoid', inputShape: [xTrain.shape[1]]}
   ));
model.add(tf.layers.dense({units: 3, activation: 'softmax'}));
model.summary();

const optimizer = tf.train.adam(params.learningRate);
model.compile({
   optimizer: optimizer,
   loss: 'categoricalCrossentropy',
   metrics: ['accuracy'],
});

아래 화면에서 볼 수 있듯 이 모델은 3가지 종을 꽤 정확히 구분한다. 그러나 매개변수를 만지다 보면 40에포크 이상 반복 시 두 가지종(동일한 군집 내) 사이의 일부 혼동이 다시 나타나는 것을 발견할 수 있다.
 
2단계 레이어 신경망 모델을 이용한 붓꽃 데이터셋 모델 학습 © IDG
 

파이썬 텐서플로우 모델을 자바스크립트로 변환하기

TensorFlow.js 리포지토리의 일부에는 저장된 텐서플로우 및 케라스 모델에 대한 컨버터가 포함돼 있다. SavedModel(텐서플로우 기본값), HDF5(케라스 기본값), 텐서플로우 허브 등 3가지 형식을 지원한다. 표준 리포지토리의 저장된 모델, 직접 학습시킨 모델, 그리고 다른 곳에서 찾은 모델에 컨버터를 사용할 수 있다.

변환 과정은 2단계로 구성된다. 첫 번째 단계에서 기존 모델을 model.json과 이진 가중치 파일로 변환하고, 두 번째 단계에서 API를 사용해 TensorFlow.js로 모델을 로드한다. 변환된 텐서플로우와 텐서플로우 허브 모델의 경우 tf.loadGraphModel, 변환된 케라스 모델의 경우 tf.loadLayersModel이다.
 

전이 학습 사용

TensorFlow.js는 텐서플로우와 사실상 같은 방식으로 전이 학습을 지원한다. 문서에는 모바일넷(MobileNet)을 자체 이미지 및 음성 명령 인식용으로 맞춤 설정하기 위한 예제를 제공한다. 기본적으로 각 코드랩에서 하는 일은 학습된 모델 위에 작은 맞춤 분류자를 추가하고 이를 학습시키는 것이다.

전반적으로 볼 때 TensorFlow.js는 텐서플로우가 할 수 있는 거의 모든 일을 할 수 있다. 그러나 TensorFlow.js의 대상 환경에는(게임용 GPU) 일반적으로 텐서플로우 딥 러닝 학습에 사용되는 대형 엔비디아 서버 GPU에 비해 활용 가능한 GPU 메모리가 많지 않으므로 브라우저에서 실행되도록 하기 위해서는 모델의 크기를 줄여야 할 수도 있다. 변환 유틸리티에서 이 작업을 어느 정도 처리하지만 수동으로 레이어를 제거하고 학습의 배치 크기를 줄여야 할 수 있다. editor@itworld.co.kr


X