오픈튜토리얼스 8.13 ~ 8.26 머신러닝야학에서 배운
레몬에이드 판매량 예측, 보스턴 집값 예측, 붓꽃 분류를 tensorflow.js로 만들었습니다.
오픈튜토리얼스 머신러닝야학 내용은 아래 링크를 참조해 주세요!
https://opentutorials.org/course/4570
nodejs version: 12.18.3
tensorflow.js version: 2.3.0
전체 코드
// csv 파일 읽기
const irisCSVPath = 'file://' + path.join(__dirname, '../data/iris.csv')
const irisCSV = tf.data.csv(irisCSVPath, {
hasHeader: true,
columnConfigs: { '품종': { isLabel: true } }
})
// 데이터셋 만들기
const irisDataset = irisCSV.map(({ xs, ys }) => {
let label = null
switch (ys['품종']) {
case 'setosa':
label = [1, 0, 0]
break;
case 'versicolor':
label = [0, 1, 0]
break;
case 'virginica':
label = [0, 0, 1]
break;
default:
break;
}
return { xs: Object.values(xs), ys: label }
}).batch(16).shuffle(10)
// 모델 만들기
const input = tf.input({ shape: [4] })
let hidden = tf.layers.dense({ units: 8 }).apply(input)
hidden = tf.layers.layerNormalization().apply(hidden)
hidden = tf.layers.activation({ activation: 'selu' }).apply(hidden)
hidden = tf.layers.dense({ units: 8 }).apply(hidden)
hidden = tf.layers.layerNormalization().apply(hidden)
hidden = tf.layers.activation({ activation: 'selu' }).apply(hidden)
hidden = tf.layers.dense({ units: 8 }).apply(hidden)
hidden = tf.layers.layerNormalization().apply(hidden)
hidden = tf.layers.activation({ activation: 'selu' }).apply(hidden)
const output = tf.layers.activation({ activation: 'softmax' }).apply(tf.layers.dense({ units: 3 }).apply(hidden))
const model = tf.model({ inputs: input, outputs: output })
model.compile({ optimizer: tf.train.adam(0.001), loss: 'categoricalCrossentropy', metrics: 'accuracy' })
model.summary()
// 모델 학습
await model.fitDataset(irisDataset, {
epochs: 1000
})
await model.fitDataset(irisDataset, {
epochs: 10,
callbacks: {
onEpochEnd: async (epoch, logs) => {
console.log(`epoch${epoch}: loss= ${logs.loss}, acc= ${logs.acc}`);
}
}
})
// 테스트 데이터로 분류 결과값 확인
const testDataset = await createTestDataSet(irisDataset, 0, 0, 8)
model.predict(testDataset.xs).print()
testDataset.ys.print()
model.getWeights()[0].print()
CSV 파일 읽기
iris csv 파일을 읽어 오면서 header를 가지고 있고 라벨이 품종이라는 점을 표시합니다.
const irisCSVPath = 'file://' + path.join(__dirname, '../data/iris.csv')
const irisCSV = tf.data.csv(irisCSVPath, {
hasHeader: true,
columnConfigs: { '품종': { isLabel: true } }
})
데이터셋 만들기
python tensorflow에서는 get_dummies 함수를 사용하면 품종 항목이 나누어집니다.
하지만 tensorflow.js에서 찾을 수가 없었습니다.
ys는 라벨을 표시한 값이 객체 형식으로 담겨져 있어 '품종'이 무엇인지 확인하고
switch 문을 사용해 값을 변경하여 줍니다.
const irisDataset = irisCSV.map(({ xs, ys }) => {
let label = null
switch (ys['품종']) {
case 'setosa':
label = [1, 0, 0]
break;
case 'versicolor':
label = [0, 1, 0]
break;
case 'virginica':
label = [0, 0, 1]
break;
default:
break;
}
return { xs: Object.values(xs), ys: label }
}).batch(16).shuffle(10)
모델 만들기
보스턴 집값 예측과 같이 layerNormalization을 사용하였습니다.
다른 점은 활성화 함수가 마지막 레이어에서 분류에 적합한 softmax를 사용합니다.
학습률은 0.001이고 모델 학습을 하면서 정확도를 파악하기 위해 metrics 값으로 'accuracy'를 추가하였습니다.
const input = tf.input({ shape: [4] })
let hidden = tf.layers.dense({ units: 8 }).apply(input)
hidden = tf.layers.layerNormalization().apply(hidden)
hidden = tf.layers.activation({ activation: 'selu' }).apply(hidden)
hidden = tf.layers.dense({ units: 8 }).apply(hidden)
hidden = tf.layers.layerNormalization().apply(hidden)
hidden = tf.layers.activation({ activation: 'selu' }).apply(hidden)
hidden = tf.layers.dense({ units: 8 }).apply(hidden)
hidden = tf.layers.layerNormalization().apply(hidden)
hidden = tf.layers.activation({ activation: 'selu' }).apply(hidden)
const output = tf.layers.activation({ activation: 'softmax' }).apply(tf.layers.dense({ units: 3 }).apply(hidden))
const model = tf.model({ inputs: input, outputs: output })
model.compile({ optimizer: tf.train.adam(0.001), loss: 'categoricalCrossentropy', metrics: 'accuracy' })
model.summary()
모델 학습과 데이터셋 분류
기존 데이터셋에서 데이터를 가져와 확인 작업을 합니다.
getweights()[0] 은 첫번째 레이어가 가지는 weights 값들입니다.
// 모델 학습
await model.fitDataset(irisDataset, {
epochs: 1000
})
await model.fitDataset(irisDataset, {
epochs: 10,
callbacks: {
onEpochEnd: async (epoch, logs) => {
console.log(`epoch${epoch}: loss= ${logs.loss}, acc= ${logs.acc}`);
}
}
})
// 테스트 데이터로 분류 결과값 확인
const testDataset = await createTestDataSet(irisDataset, 0, 0, 8)
model.predict(testDataset.xs).print()
testDataset.ys.print()
model.getWeights()[0].print()
결과값과 실제값 비교:
Tensor
[[0.0000133, 0.999977 , 0.0000097],
[4e-7 , 0.9999844, 0.0000151],
[0.0176175, 0.9823747, 0.0000078],
[0.0000022, 0.9999913, 0.0000065],
[0.0001166, 0.0010784, 0.998805 ],
[0.0000383, 0.0020841, 0.9978777],
[0.0000362, 0.002025 , 0.9979388],
[0.0000181, 0.0106683, 0.9893135]]
Tensor
[[0, 1, 0],
[0, 1, 0],
[0, 1, 0],
[0, 1, 0],
[0, 0, 1],
[0, 0, 1],
[0, 0, 1],
[0, 0, 1]]
https://js.tensorflow.org/api/2.3.0/
'머신러닝' 카테고리의 다른 글
tensorflow.js 2) 보스턴 집값 예측 (0) | 2020.08.27 |
---|---|
tensorflow.js 1) 레몬에이드 판매량 예측 (0) | 2020.08.27 |