Tensorflow.js를 사용한 프론트엔드 개발자를 위한 머신 러닝

게시 됨: 2022-03-10
빠른 요약 ↬ 자바스크립트와 Tensorflow.js와 같은 프레임워크를 사용하는 것은 머신 러닝을 시작하고 자세히 배울 수 있는 좋은 방법입니다. 이 기사에서 Charlie Gerard는 현재 Tensorflow.js를 사용하여 사용할 수 있는 세 가지 주요 기능을 다루고 프런트엔드에서 머신 러닝을 사용하는 것의 한계에 대해 설명합니다.

머신 러닝은 종종 데이터 과학자와 Python 개발자의 영역에 속하는 것처럼 느껴집니다. 그러나 지난 몇 년 동안 JavaScript를 비롯한 다양한 프로그래밍 언어에서 더 쉽게 액세스할 수 있도록 오픈 소스 프레임워크가 만들어졌습니다. 이 기사에서는 Tensorflow.js를 사용하여 몇 가지 예제 프로젝트를 통해 브라우저에서 기계 학습을 사용할 수 있는 다양한 가능성을 탐색합니다.

머신 러닝이란 무엇입니까?

일부 코드를 살펴보기 전에 머신 러닝이 무엇인지, 핵심 개념과 용어에 대해 간략하게 설명하겠습니다.

정의

일반적인 정의는 명시적으로 프로그래밍하지 않고도 컴퓨터가 데이터에서 학습하는 능력입니다.

이를 기존 프로그래밍과 비교하면 컴퓨터가 무엇을 찾아야 하는지 정확히 말할 필요 없이 데이터의 패턴을 식별하고 예측을 생성할 수 있다는 의미입니다.

사기 탐지의 예를 들어 보겠습니다. 거래가 사기인지 아닌지를 알기 위한 정해진 기준은 없습니다. 사기는 모든 국가, 모든 계정, 모든 고객을 대상으로 언제라도 실행될 수 있습니다. 이 모든 것을 수동으로 추적하는 것은 거의 불가능합니다.

그러나 수년에 걸쳐 수집된 사기성 비용에 대한 이전 데이터를 사용하여 이 데이터의 패턴을 이해하는 기계 학습 알고리즘을 훈련하여 새로운 트랜잭션이 제공될 수 있는 모델을 생성하고 사기성 여부를 예측할 수 있습니다. 정확히 무엇을 찾아야 하는지 알려줍니다.

점프 후 더! 아래에서 계속 읽기 ↓

핵심 개념

다음 코드 샘플을 이해하려면 먼저 몇 가지 일반적인 용어를 다루어야 합니다.

모델

데이터 세트로 기계 학습 알고리즘을 훈련할 때 모델은 이 훈련 프로세스의 출력입니다. 새로운 데이터를 입력으로 받고 예측을 출력으로 생성하는 함수와 약간 비슷합니다.

레이블 및 기능

레이블 및 기능은 학습 프로세스에서 알고리즘에 제공하는 데이터와 관련됩니다.

레이블은 데이터세트의 각 항목을 분류하는 방법과 레이블을 지정하는 방법을 나타냅니다. 예를 들어 데이터 세트가 다양한 동물을 설명하는 CSV 파일인 경우 레이블은 "고양이", "개" 또는 "뱀"(각 동물이 나타내는 것에 따라 다름)과 같은 단어가 될 수 있습니다.

반면에 기능은 데이터 세트에 있는 각 항목의 특성입니다. 동물의 경우 "수염, 야옹", "장난감, 짖는 소리", "파충류, 만연" 등과 같은 것일 수 있습니다.

이를 사용하여 기계 학습 알고리즘은 향후 예측에 사용할 기능과 해당 레이블 간의 상관 관계를 찾을 수 있습니다.

신경망

신경망은 인공 뉴런 층을 사용하여 뇌가 작동하는 방식을 모방하려고 시도하는 일련의 기계 학습 알고리즘입니다.

이 기사에서 작동 방식에 대해 자세히 설명할 필요는 없지만 더 자세히 알고 싶다면 여기 정말 좋은 동영상이 있습니다.

기계 학습에서 일반적으로 사용되는 몇 가지 용어를 정의했으므로 이제 JavaScript와 Tensorflow.js 프레임워크를 사용하여 수행할 수 있는 작업에 대해 이야기해 보겠습니다.

특징

현재 세 가지 기능을 사용할 수 있습니다.

  1. 사전 훈련된 모델을 사용하여,
  2. 전이 학습,
  3. 고유한 모델 정의, 실행 및 사용.

가장 간단한 것부터 시작하겠습니다.

1. 사전 훈련된 모델 사용

해결하려는 문제에 따라 코드에서 활용하고 가져올 수 있는 특정 목적과 특정 데이터 세트로 이미 훈련된 모델이 있을 수 있습니다.

예를 들어 이미지가 고양이 사진인지 예측하는 웹사이트를 구축한다고 가정해 보겠습니다. 인기 있는 이미지 분류 모델은 MobileNet 이라고 하며 Tensorflow.js로 사전 훈련된 모델로 사용할 수 있습니다.

이에 대한 코드는 다음과 같습니다.

 <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Cat detection</title> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]"> </script> <script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/[email protected]"> </script> </head> <body> <img alt="cat laying down" src="cat.jpeg"/> <script> const img = document.getElementById('image'); const predictImage = async () => { console.log("Model loading..."); const model = await mobilenet.load(); console.log("Model is loaded!") const predictions = await model.classify(img); console.log('Predictions: ', predictions); } predictImage(); </script> </body> </html>

HTML 헤드에서 Tensorflow.js와 MobileNet 모델을 가져오는 것으로 시작합니다.

 <script src="https://cdnjs.cloudflare.com/ajax/libs/tensorflow/1.0.1/tf.js"> </script> <script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/[email protected]"> </script>

그런 다음 본문 내부에 예측에 사용할 이미지 요소가 있습니다.

 <img alt="cat laying down" src="cat.jpeg"/>

마지막으로 script 태그 내부에는 사전 훈련된 MobileNet 모델을 로드하고 image 태그에서 찾은 이미지를 분류하는 JavaScript 코드가 있습니다. 확률 점수에 따라 정렬된 3개의 예측 배열을 반환합니다(첫 번째 요소가 가장 좋은 예측임).

 const predictImage = async () => { console.log("Model loading..."); const model = await mobilenet.load(); console.log("Model is loaded!") const predictions = await model.classify(img); console.log('Predictions: ', predictions); } predictImage();

그리고 그게 다야! 이것이 Tensorflow.js로 브라우저에서 사전 훈련된 모델을 사용할 수 있는 방법입니다!

참고 : MobileNet 모델이 분류할 수 있는 다른 항목을 보려면 Github에서 사용 가능한 다양한 클래스 목록을 찾을 수 있습니다.

알아야 할 중요한 사실은 브라우저에서 사전 훈련된 모델을 로드하는 데 시간이 걸릴 수 있으므로(때로는 최대 10초) 사용자가 영향을 받지 않도록 인터페이스를 사전 로드하거나 조정하는 것이 좋습니다.

Tensorflow.js를 NPM 모듈로 사용하는 것을 선호하는 경우 다음과 같이 모듈을 가져와서 사용할 수 있습니다.

 import * as mobilenet from '@tensorflow-models/mobilenet';

CodeSandbox에서 이 예제를 자유롭게 사용해 보십시오.

사전 훈련된 모델을 사용하는 방법을 살펴보았으므로 사용 가능한 두 번째 기능인 전이 학습을 살펴보겠습니다.

2. 전이 학습

전이 학습은 사전 훈련된 모델을 맞춤형 훈련 데이터와 결합하는 기능입니다. 이것이 의미하는 바는 처음부터 모든 것을 만들 필요 없이 모델의 기능을 활용하고 고유한 샘플을 추가할 수 있다는 것입니다.

예를 들어, 알고리즘은 이미지 분류 모델을 생성하기 위해 수천 개의 이미지로 훈련되었으며, 자체적으로 생성하는 대신 이전 학습을 통해 새로운 사용자 지정 이미지 샘플을 사전 훈련된 모델과 결합하여 새로운 이미지 분류기를 생성할 수 있습니다. 이 기능을 사용하면 더욱 맞춤화된 분류기를 매우 빠르고 쉽게 사용할 수 있습니다.

이것이 코드에서 어떻게 보이는지에 대한 예를 제공하기 위해 이전 예의 용도를 변경하고 새 이미지를 분류할 수 있도록 수정하겠습니다.

참고 : 최종 결과는 여기에서 실시간으로 시도할 수 있는 아래의 실험입니다.

(라이브 데모) (큰 미리보기)

다음은 이 설정의 가장 중요한 부분에 대한 몇 가지 코드 샘플이지만 전체 코드를 살펴봐야 하는 경우 이 CodeSandbox에서 찾을 수 있습니다.

Tensorflow.js와 MobileNet을 가져와서 시작해야 하지만 이번에는 KNN(k-최근접 이웃) 분류기도 추가해야 합니다.

 <!-- Load TensorFlow.js --> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script> <!-- Load MobileNet --> <script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/mobilenet"></script> <!-- Load KNN Classifier --> <script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/knn-classifier"></script>

분류기가 필요한 이유는 (MobileNet 모듈만 사용하는 대신) 이전에 본 적이 없는 사용자 지정 샘플을 추가하기 때문입니다. 따라서 KNN 분류기를 사용하면 모든 것을 함께 결합하고 결합된 데이터에 대해 예측을 실행할 수 있습니다.

그런 다음 고양이 이미지를 video 태그로 교체하여 카메라 피드의 이미지를 사용할 수 있습니다.

 <video autoplay width="227" height="227"></video>

마지막으로 일부 비디오 샘플을 기록하고 예측을 시작하기 위해 레이블로 사용할 몇 개의 버튼을 페이지에 추가해야 합니다.

 <section> <button class="button">Left</button> <button class="button">Right</button> <button class="test-predictions">Test</button> </section>

이제 몇 가지 중요한 변수를 설정하여 시작할 JavaScript 파일로 이동하겠습니다.

 // Number of classes to classify const NUM_CLASSES = 2; // Labels for our classes const classes = ["Left", "Right"]; // Webcam Image size. Must be 227. const IMAGE_SIZE = 227; // K value for KNN const TOPK = 10; const video = document.getElementById("webcam");

이 특정 예에서 우리는 머리를 왼쪽 또는 오른쪽으로 기울이는 것 사이에서 웹캠 입력을 분류할 수 있기를 원하므로 leftright 레이블이 지정된 두 개의 클래스가 필요합니다.

227로 설정된 이미지 크기는 픽셀 단위의 비디오 요소 크기입니다. Tensorflow.js 예제를 기반으로 이 값은 MobileNet 모델이 훈련된 데이터 형식과 일치하도록 227로 설정해야 합니다. 새로운 데이터를 분류할 수 있으려면 후자가 동일한 형식에 맞아야 합니다.

더 크게 해야 하는 경우 가능하지만 KNN 분류기에 데이터를 제공하기 전에 데이터를 변환하고 크기를 조정해야 합니다.

그런 다음 K 값을 10으로 설정합니다. KNN 알고리즘의 K 값은 새 입력의 클래스를 결정할 때 고려하는 인스턴스의 수를 나타내기 때문에 중요합니다.

이 경우 값 10은 새로운 데이터에 대한 레이블을 예측할 때 훈련 데이터에서 10개의 가장 가까운 이웃을 살펴보고 새 입력을 분류하는 방법을 결정한다는 것을 의미합니다.

마지막으로 video 요소를 가져옵니다. 논리의 경우 모델과 분류자를 로드하여 시작하겠습니다.

 async load() { const knn = knnClassifier.create(); const mobilenetModule = await mobilenet.load(); console.log("model loaded"); }

그런 다음 비디오 피드에 액세스해 보겠습니다.

 navigator.mediaDevices .getUserMedia({ video: true, audio: false }) .then(stream => { video.srcObject = stream; video.width = IMAGE_SIZE; video.height = IMAGE_SIZE; });

그런 다음 샘플 데이터를 기록하기 위해 몇 가지 버튼 이벤트를 설정해 보겠습니다.

 setupButtonEvents() { for (let i = 0; i < NUM_CLASSES; i++) { let button = document.getElementsByClassName("button")[i]; button.onmousedown = () => { this.training = i; this.recordSamples = true; }; button.onmouseup = () => (this.training = -1); } }

웹캠 이미지 샘플을 가져와서 다시 포맷하고 MobileNet 모듈과 결합하는 함수를 작성해 보겠습니다.

 // Get image data from video element const image = tf.browser.fromPixels(video); let logits; // 'conv_preds' is the logits activation of MobileNet. const infer = () => this.mobilenetModule.infer(image, "conv_preds"); // Train class if one of the buttons is held down if (this.training != -1) { logits = infer(); // Add current image to classifier this.knn.addExample(logits, this.training); }

마지막으로 웹캠 이미지를 수집하고 나면 다음 코드로 예측을 테스트할 수 있습니다.

 logits = infer(); const res = await this.knn.predictClass(logits, TOPK); const prediction = classes[res.classIndex];

마지막으로 더 이상 필요하지 않은 웹캠 데이터를 삭제할 수 있습니다.

 // Dispose image when done image.dispose(); if (logits != null) { logits.dispose(); }

다시 한 번, 전체 코드를 보고 싶다면 앞서 언급한 CodeSandbox에서 찾을 수 있습니다.

3. 브라우저에서 모델 훈련

마지막 기능은 브라우저에서 완전히 모델을 정의, 훈련 및 실행하는 것입니다. 이것을 설명하기 위해 우리는 홍채를 인식하는 고전적인 예를 만들 것입니다.

이를 위해 오픈 소스 데이터 세트를 기반으로 Irises를 Setosa, Virginica 및 Versicolor의 세 가지 범주로 분류할 수 있는 신경망을 생성합니다.

시작하기 전에 여기 라이브 데모 링크가 있으며 전체 코드를 가지고 놀고 싶다면 여기 CodeSandbox가 있습니다.

모든 기계 학습 프로젝트의 핵심에는 데이터 세트가 있습니다. 우리가 수행해야 하는 첫 번째 단계 중 하나는 이 데이터 세트를 훈련 세트와 테스트 세트로 분할하는 것입니다.

그 이유는 훈련 세트를 사용하여 알고리즘을 훈련하고 테스트 세트를 사용하여 예측의 정확성을 확인하고 모델을 사용할 준비가 되었는지 또는 조정할 필요가 있는지 확인하기 때문입니다.

참고 : 쉽게 하기 위해 이미 훈련 세트와 테스트 세트를 CodeSanbox에서 찾을 수 있는 두 개의 JSON 파일로 분할했습니다.

훈련 세트에는 130개의 항목과 테스트 세트 14개가 포함되어 있습니다. 이 데이터가 어떻게 보이는지 살펴보면 다음과 같습니다.

 { "sepal_length": 5.1, "sepal_width": 3.5, "petal_length": 1.4, "petal_width": 0.2, "species": "setosa" }

우리가 볼 수 있는 것은 꽃받침과 꽃잎의 길이와 너비에 대한 네 가지 다른 특징과 종에 대한 레이블입니다.

Tensorflow.js와 함께 사용할 수 있으려면 이 데이터를 프레임워크가 이해할 수 있는 형식으로 만들어야 합니다. 이 경우 훈련 데이터의 경우 4가지 기능이 있는 130개 샘플에 대해 [130, 4] 가 됩니다. 아이리스.

 import * as trainingSet from "training.json"; import * as testSet from "testing.json"; const trainingData = tf.tensor2d( trainingSet.map(item => [ item.sepal_length, item.sepal_width, item.petal_length, item.petal_width ]), [130, 4] ); const testData = tf.tensor2d( testSet.map(item => [ item.sepal_length, item.sepal_width, item.petal_length, item.petal_width ]), [14, 4] );

다음으로 출력 데이터도 모양을 지정해야 합니다.

 const output = tf.tensor2d(trainingSet.map(item => [ item.species === 'setosa' ? 1 : 0, item.species === 'virginica' ? 1 : 0, item.species === 'versicolor' ? 1 : 0 ]), [130,3])

그런 다음 데이터가 준비되면 모델 생성으로 넘어갈 수 있습니다.

 const model = tf.sequential(); model.add(tf.layers.dense( { inputShape: 4, activation: 'sigmoid', units: 10 } )); model.add(tf.layers.dense( { inputShape: 10, units: 3, activation: 'softmax' } ));

위의 코드 샘플에서는 순차 모델을 인스턴스화하고 입력 및 출력 레이어를 추가하는 것으로 시작합니다.

내부에서 사용되는 매개변수( inputShape , activationunits )는 생성하는 모델, 사용된 데이터 유형 등에 따라 다를 수 있으므로 이 게시물의 범위를 벗어납니다.

모델이 준비되면 데이터를 사용하여 모델을 훈련할 수 있습니다.

 async function train_data(){ for(let i=0;i<15;i++){ const res = await model.fit(trainingData, outputData,{epochs: 40}); } } async function main() { await train_data(); model.predict(testSet).print(); }

이것이 잘 작동하면 테스트 데이터를 사용자 지정 사용자 입력으로 교체하기 시작할 수 있습니다.

main 함수를 호출하면 예측의 출력은 다음 세 가지 옵션 중 하나처럼 보일 것입니다.

 [1,0,0] // Setosa [0,1,0] // Virginica [0,0,1] // Versicolor

예측은 데이터가 세 클래스 중 하나에 속할 확률을 나타내는 세 숫자의 배열을 반환합니다. 1에 가장 가까운 숫자가 가장 높은 예측값입니다.

예를 들어 분류의 출력이 [0.0002, 0.9494, 0.0503] 이면 배열의 두 번째 요소가 가장 높으므로 모델은 새 입력이 Virginica일 가능성이 있다고 예측했습니다.

그리고 이것이 Tensorflow.js의 간단한 신경망을 위한 것입니다!

우리는 Irises의 작은 데이터 세트에 대해서만 이야기했지만 더 큰 데이터 세트로 이동하거나 이미지로 작업하려는 경우 단계는 동일합니다.

  • 데이터 수집
  • 훈련 세트와 테스트 세트 간 분할
  • Tensorflow.js가 이해할 수 있도록 데이터를 다시 포맷합니다.
  • 알고리즘 선택
  • 데이터 피팅;
  • 예측.

생성된 모델을 다른 애플리케이션에 로드하고 새 데이터를 예측할 수 있도록 저장하려면 다음 줄을 사용하여 수행할 수 있습니다.

 await model.save('file:///path/to/my-model'); // in Node.js

참고 : 모델을 저장하는 방법에 대한 추가 옵션은 이 리소스를 참조하세요.

제한

그게 다야! Tensorflow.js를 사용하여 현재 사용할 수 있는 세 가지 주요 기능을 살펴보았습니다!

마치기 전에 프론트엔드에서 머신 러닝을 사용하는 것의 몇 가지 한계를 간략하게 언급하는 것이 중요하다고 생각합니다.

1. 성능

외부 소스에서 사전 훈련된 모델을 가져오면 애플리케이션의 성능에 영향을 미칠 수 있습니다. 예를 들어 일부 개체 감지 모델은 10MB를 초과하므로 웹사이트 속도가 크게 느려집니다. 사용자 경험에 대해 생각하고 자산 로드를 최적화하여 인지된 성능을 향상시키십시오.

2. 입력 데이터의 품질

모델을 처음부터 구축하는 경우 자체 데이터를 수집하거나 일부 오픈 소스 데이터 세트를 찾아야 합니다.

어떤 종류의 데이터 처리를 하거나 다른 알고리즘을 시도하기 전에 입력 데이터의 품질을 확인하십시오. 예를 들어 텍스트 조각의 감정을 인식하는 감정 분석 모델을 구축하려는 경우 모델을 훈련하는 데 사용하는 데이터가 정확하고 다양한지 확인하십시오. 사용된 데이터의 품질이 낮으면 훈련 결과가 쓸모가 없습니다.

3. 책임

오픈 소스 사전 훈련 모델을 사용하면 매우 빠르고 쉽게 할 수 있습니다. 그러나 그것은 또한 그것이 어떻게 생성되었는지, 데이터 세트가 무엇으로 구성되었는지, 심지어 어떤 알고리즘이 사용되었는지 항상 알지 못한다는 것을 의미합니다. 일부 모델은 "블랙 박스"라고 하며, 이는 특정 출력을 예측한 방법을 실제로 알지 못한다는 것을 의미합니다.

구축하려는 대상에 따라 문제가 될 수 있습니다. 예를 들어, 기계 학습 모델을 사용하여 스캔 이미지를 기반으로 누군가가 암에 걸릴 확률을 감지하는 데 도움이 되는 경우 위음성(모델은 실제로 암에 걸렸을 때 암에 걸리지 않았다고 예측한 경우)의 경우 실제 법적 책임이 있을 수 있으며 모델이 특정 예측을 한 이유를 설명할 수 있어야 합니다.

요약

결론적으로 자바스크립트와 Tensorflow.js와 같은 프레임워크를 사용하는 것은 기계 학습을 시작하고 자세히 배울 수 있는 좋은 방법입니다. 프로덕션 준비가 된 응용 프로그램은 Python과 같은 언어로 빌드되어야 하지만 JavaScript를 사용하면 개발자가 다른 기능을 배우기 위해 시간을 투자하기 전에 다양한 기능을 가지고 놀고 기본 개념을 더 잘 이해할 수 있습니다. 언어.

이 튜토리얼에서는 Tensorflow.js를 사용하여 가능한 것만 다루었지만 다른 라이브러리 및 도구의 생태계는 성장하고 있습니다. 더 많은 지정된 프레임워크도 사용할 수 있으므로 Magenta.js로 음악과 같은 다른 도메인에서 기계 학습을 사용하여 탐색하거나 웹 사이트에서 사용자 탐색을 예측할 수 있습니다.

도구의 성능이 향상됨에 따라 JavaScript로 기계 학습 지원 응용 프로그램을 구축할 수 있는 가능성이 점점 더 커지고 있으며 커뮤니티에서 액세스 가능하도록 노력하고 있으므로 지금이 이에 대해 자세히 알아볼 수 있는 좋은 시간입니다.

추가 리소스

더 자세히 알아보려면 다음 리소스를 참조하세요.

기타 프레임워크 및 도구

  • ml5.js
  • ml.js
  • 브레인.js
  • 케라스.js
  • 포즈넷
  • 텐서플로 놀이터

예, 모델 및 데이터 세트

  • Tensorflow.js 모델
  • Tensorflow.js 예시
  • 데이터세트

영감

  • 가르칠 수 있는 기계
  • AI 실험
  • AIJS.rock
  • 창의성

읽어 주셔서 감사합니다!