從零開始的機器學習生活 – TensorFlow.js 學習顏色分類
在前面幾篇文章補足了一些基本知識之後,接著我們就可以進行一些基本的練習,本次做的是透過機器學習辨識顏色,下面將會附上程式碼以及 github page。如果你是 IOS 12 或是 Android 9 這些較新版本手機使用者,會有無法運算的 BUG 存在,只能靜待修復了。
資料
在寫程式之前,我們先談論關於資料來源這件事情,你可以自己收集資料、根據規則用程式產生資料(ex:衣服尺寸表)或是用 google 的 Dataset Search 本次的資料來源則用教學 CodingTrain 的顏色資料。
程式範例
先上 demo 以及 github 本次一起使用 P5.js 來實作,以下只貼出 js 的部分。
let data
let colors = []
let xs, ys
let model
let labels = []
let rSlider, gSlider, bSlider
let labelList = [
'紅色系',
'綠色系',
'藍色系',
'橘色系',
'黃色系',
'粉色系',
'紫色系',
'棕色系',
'灰色系',
]
function preload() {
data = loadJSON('color.json')
}
function setup() {
let canvas = createCanvas(300, 300).parent('canvas')
rSlider = createSlider(0, 255, 255).parent('sliderR')
gSlider = createSlider(0, 255, 0).parent('sliderG')
bSlider = createSlider(0, 255, 0).parent('sliderB')
for (let record of data.entries) {
let col = [record.r / 255, record.g / 255, record.b / 255] //Normalization
colors.push(col)
labels.push(labelList.indexOf(record.label))
}
xs = tf.tensor2d(colors)
// console.log(xs.shape) //[row,col]
let labelsTensor = tf.tensor1d(labels, 'int32')
// labelsTensor.print()
ys = tf.oneHot(labelsTensor, 9) // one hot encoding
model = tf.sequential()
let hiddenLayer = tf.layers.dense({
units: 32, // 此隱藏層的神經元數量
inputDim: 3, // R,G,B 三種 input
activation: 'sigmoid', // 激活函數
})
let outputLayer = tf.layers.dense({
units: 9, // 9 種 label
activation: 'softmax',
})
model.add(hiddenLayer)
model.add(outputLayer)
const learnRate = 0.2
const optimizer = tf.train.sgd(learnRate) // 梯度下降法
model.compile({
optimizer: optimizer,
loss: 'categoricalCrossentropy' // 優化 loss 演算法 for 分類問題
})
train().then((res) => {
console.log(res.history.loss)
})
}
async function train() {
const options = {
epochs: 30, // 輪迴訓練次數
validationSplit: 0.1, // 10% 資料驗證
shuffle: true, // 亂數取樣
callbacks: {
// onTrainBegin: () => console.log('onTrainBegin'),
// onTrainEnd: () => console.log('onTrainEnd'),
// onEpochBegin: () => console.log('onEpochBegin'),
onEpochEnd: (num, logs) => {
document.getElementById("status").innerHTML = `epochs: ${num} 結束, Loss值: ${logs.loss}`
// console.log(`epochs: ${num} 結束, Loss值: ${logs.loss}`)
// console.log(logs)
},
// onBatchBegin: () => console.log('onBatchBegin'),
onBatchEnd: () => {
// console.log('onBatchEnd')
return tf.nextFrame()
}
}
}
return await model.fit(xs, ys, options)
}
function draw() {
let r = rSlider.value();
let g = gSlider.value();
let b = bSlider.value();
background(r, g, b);
strokeWeight(2);
stroke(255);
line(frameCount % width, 0, frameCount % width, height);
// 防止記憶體被吃光
tf.tidy(() => {
const xs = tf.tensor2d([
[r / 255, g / 255, b / 255]
])
let result = model.predict(xs)
let index = result.argMax(1).dataSync() //拿取機率最高的 index
let label = labelList[index]
document.getElementById("result").innerHTML= label
// console.log(label)
// console.log(tf.memory().numTensors)
// result.print()
})
}
稍微講解一下程式架構,程式碼內也有註解。
- 色碼進行 Normalization
- label 進行 one hot encoding
- 定義整個 model 結構
- 使用 梯度下降法 尋找最優解
- categoricalCrossentropy 優化 loss
- 訓練參數
- 預測結果輸出
上面幾行程式碼就可以寫出一個簡單的顏色預測功能,如果你不太了解某些地方為何要使用這些演算法可以看看 [資料分析&機器學習] 第2.4講:資料前處理(Missing data, One-hot encoding, Feature Scaling)