data load and visualize
실행환경
•
web browser
import
<!DOCTYPE html>
<html>
<head>
<title>TensorFlow.js Tutorial</title>
<!-- Import TensorFlow.js -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.0.0/dist/tf.min.js"></script>
<!-- Import tfjs-vis 시각화를 위한 라이브러리-->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-vis@1.0.2/dist/tfjs-vis.umd.min.js"></script>
<!-- Import the main script file -->
<script src="script.js"></script>
</head>
<body>
</body>
</html>
HTML
복사
visualize
//script.js
async function run() {
// Load and plot the original input data that we are going to train on.
const data = await getData(); // 데이터 형태는 { horsepower:number; mpg: number }[] 이다
console.log(data);
const values = data.map((d) => ({
x: d.horsepower,
y: d.mpg,
}));
tfvis.render.scatterplot(
{ name: "Horsepower v MPG" },
{ values },
{
xLabel: "Horsepower",
yLabel: "MPG",
height: 300,
}
);
// More code will be added below
}
async function getData() {
const carsDataReq = await fetch(
"https://storage.googleapis.com/tfjs-tutorials/carsData.json"
);
const carsData = await carsDataReq.json();
const cleaned = carsData
.map((car) => ({
mpg: car.Miles_per_Gallon,
horsepower: car.Horsepower,
}))
.filter((car) => car.mpg != null && car.horsepower != null);
return cleaned;
}
run();
JavaScript
복사
Define the model architecture
function createModel() {
const model = tf.sequential(); // 모델을 인스턴스화 (tf.Model 객체 생성)
// Add a single input layer
model.add(tf.layers.dense({inputShape: [1], units: 1, useBias: true}));
// Add an output layer
model.add(tf.layers.dense({units: 1, useBias: true}));
return model;
}
JavaScript
복사
•
sequential 은 model 을 인스턴스화 한다.
•
첫번째 model.add 에서는 인풋 레이어를 추가하는 것이다. 이 레이어는 자동으로 dense 레이어와 연결되는데, 이 dense 레이어는
Wx + b
의 형태로 나타난다.
•
sequential 모델은 inputShape를 정의 해야 한다. 현재 데이터에서는 [1]로 정의했는데 x값이 한개 밖에 없기 때문이다.(horsepower)
•
unints 는 해당 레이어에 weight 의 크기를 설정한다.
•
useBias 는 bias(Wx + b 에서 b)를 사용할 것인지 사용하는 옵션이다. 기본값으로 true 인데 굳이 true로 했다.
•
마지막 model.add 에서는 모델에 output 레이어를 추가하는 것이다. units 를 1로 설정한 것은 output 이 1개의 number 를 반환할 것이기 때문이다. (목표는 input: horsepower, output: mps !)
Visualize Model!
const model = createModel();
tfvis.show.modelSummary({name: 'Model Summary'}, model);
JavaScript
복사
Training 을 위한 데이터 preset!
성능적인 이점을 얻기 위해서는 데이터를 tensor 로 변환할 필요가 있다. 그리고 shuffling 과 nomalization 을 수행할 것이다.(best practice)
function convertToTensor(data) {
return tf.tidy(() => {
// Step 1. Shuffle the data
tf.util.shuffle(data);
// Step 2. Convert data to Tensor
const inputs = data.map(d => d.horsepower)
const labels = data.map(d => d.mpg);
const inputTensor = tf.tensor2d(inputs, [inputs.length, 1]);
const labelTensor = tf.tensor2d(labels, [labels.length, 1]);
//Step 3. Normalize the data to the range 0 - 1 using min-max scaling
const inputMax = inputTensor.max();
const inputMin = inputTensor.min();
const labelMax = labelTensor.max();
const labelMin = labelTensor.min();
const normalizedInputs = inputTensor.sub(inputMin).div(inputMax.sub(inputMin));
const normalizedLabels = labelTensor.sub(labelMin).div(labelMax.sub(labelMin));
return {
inputs: normalizedInputs,
labels: normalizedLabels,
// Return the min/max bounds so we can use them later.
inputMax,
inputMin,
labelMax,
labelMin,
}
});
}
JavaScript
복사
shuffling!
•
shuffle 은 모델에 학습시킬 데이터의 순서를 randomize 한다.
•
데이터 셋의 하위 집합인 배치에 고른 분포를 줄 수 있기 때문에 이 순서를 shuffle 하는 것이 중요하다.
(데이터의 순서에 따라 학습의 결과가 달라지지 않도록!)
•
항상 모델을 학습시키기 전에 shuffling 하는 것이 Best Practice 다!
convert to tensors
•
tensor2d 를 통해서 2d 형태의 텐서를 생성한다.
•
inputs 과 labels 를 생성해준다.
normalize the data
•
•
tensorflow.js 로 빌드할 머신러닝 모델의 내부는 너무 크지 않은 숫자로 작동하도록 설계되었으므로 normalization 이 중요하다!
•
이 또한 Best Practice
•
데이터를 텐서로 만들기 전에도 정규화 할 수 있지만, 백터화(tensor)를 활용하면 for 루프를 사용하지 않고도 스케일링 작업을 수행할 수 있으므로 나중에 수행하는 것이 편할 것이다!
•
마지막에 정규화된 값들과 함께 정규화 범위도 반환한다. 이는 훈련중에 정규화에 사용한 값을 유지해서 출력을 정규화하지 않고 원래 스케일로 출력할 수 있도록 하기 위해서, 그리고 추가로 입력되는 데이터들을 동일한 방식으로 정규화 할 수 있도록 한다!
Training the Model!!
async function trainModel(model, inputs, labels) {
// Prepare the model for training.
model.compile({
optimizer: tf.train.adam(),
loss: tf.losses.meanSquaredError,
metrics: ['mse'],
});
const batchSize = 32;
const epochs = 50;
return await model.fit(inputs, labels, {
batchSize,
epochs,
shuffle: true,
callbacks: tfvis.show.fitCallbacks(
{ name: 'Training Performance' },
['loss', 'mse'],
{ height: 200, callbacks: ['onEpochEnd'] }
)
});
}
JavaScript
복사
prepare training
•
loss: 모델에게 제공된 데이터 batch 들을 잘 학습하고 있는지 알려주는 함수. 위에서는 평균 제곱 오차를 사용하고있다.
•
batchSize 는 32로 설정. 보통 32 ~512 범위에 있다. 모든 문제에 이상적인 배치 크기는 없다! 데이터 셋의 크기와 목적에 맞게 설정하는 것이 좋다!
•
epochs 는 모델이 데이터 세트를 보려는 횟수를 나타낸다. 위 코드에서는 데이터 세트를 50번 반복해서 볼 것.
•
fix 함수를 통해서 학습 시작
•
학습 진행 상황을 모니터링 하기 위해 callback 으로 visualize 함수를 내보낸다
// run 함수에 추가
// Convert the data to a form we can use for training.
const tensorData = convertToTensor(data);
const {inputs, labels} = tensorData;
// Train the model
await trainModel(model, inputs, labels);
console.log('Done Training');
JavaScript
복사
Prediction
이제 학습된 모델을 통해서 예측을 해보자!!!
function testModel(model, inputData, normalizationData) {
const {inputMax, inputMin, labelMin, labelMax} = normalizationData;
// Generate predictions for a uniform range of numbers between 0 and 1;
// We un-normalize the data by doing the inverse of the min-max scaling
// that we did earlier.
const [xs, preds] = tf.tidy(() => {
const xs = tf.linspace(0, 1, 100);
const preds = model.predict(xs.reshape([100, 1]));
const unNormXs = xs
.mul(inputMax.sub(inputMin))
.add(inputMin);
const unNormPreds = preds
.mul(labelMax.sub(labelMin))
.add(labelMin);
// Un-normalize the data
return [unNormXs.dataSync(), unNormPreds.dataSync()];
});
const predictedPoints = Array.from(xs).map((val, i) => {
return {x: val, y: preds[i]}
});
const originalPoints = inputData.map(d => ({
x: d.horsepower, y: d.mpg,
}));
tfvis.render.scatterplot(
{name: 'Model Predictions vs Original Data'},
{values: [originalPoints, predictedPoints], series: ['original', 'predicted']},
{
xLabel: 'Horsepower',
yLabel: 'MPG',
height: 300
}
);
}
JavaScript
복사
•
lintspace 를 통해서 모델에 공급할 100개의 새로운 예(example)을 생성한다
•
predict 를 통해서 model 에 예를 전달한다
•
테이터를 normaiize 된 값이 아닌 원본 값을 가져오도록 역 정규화를 한다.
•
tensor.dattaSync 를 통해서
// run 코드에 추가한다
testModel(model, data, tensorData);
JavaScript
복사
용어
텐서(tensor)
텐서플로우 프로그램의 기본 데이터 구조입니다. 텐서는 대부분 스칼라, 벡터 또는 행렬로 이루어진 N차원 데이터 구조이며, N은 매우 큰 수일 수 있습니다. 텐서의 요소는 정수, 부동 소수점 또는 문자열 값을 포함할 수 있습니다.
정규화(normalization)
실제 값 범위를 표준 값 범위(일반적으로 -1~+1 또는 0~1)로 변환하는 과정입니다. 예를 들어 어떤 특성의 원래 범위가 800~6,000인 경우, 뺄셈과 나눗셈을 거쳐 값 범위를 -1~+1로 정규화할 수 있습니다.
옵티마이저(optimizer)
경사하강법 알고리즘의 구체적인 구현입니다. 옵티마이저에 대한 텐서플로우의 기본 클래스는 tf.train.Optimizer입니다. 다른 옵티마이저는 다음 중 하나 이상의 개념을 활용하여 주어진 학습 세트에서 경사하강법의 효과를 강화할 수 있습니다.
평균 제곱 오차(MSE, Mean Squared Error)
예시당 평균 제곱 손실입니다. MSE는 제곱 손실을 예시의 개수로 나누어 계산합니다. 텐서플로우 플레이그라운드에서 '학습 손실' 및 '테스트 손실'로 표시하는 값이 MSE입니다.
세대(epoch)
전체 데이터 세트의 각 예를 한 번씩 확인한 전체 학습 단계입니다. 따라서 한 세대(이폭)는 N/배치 크기 학습 반복을 나타내며, 여기에서 N은 총 예시 수입니다.