关于具有 2 个特征的 Tensorflow 分类模型的问题
Question about Tensorflow classification model with 2 features
我正在尝试在 Tensorflow.js 中构建模型以 class 验证 2 个特征。
Input (training) data screenshot for clarity <- "Class" 有 A 和 B 特征输入的标签。
我的结果如下所示:
Results where "Pred-Class" is predicted by model
因此,根据结果,我想向社区询问下一个问题:
1. 我正在为模型提供下一个张量 classification 的 One Hot 值:
[[0, 1, 0],
[0, 0, 0],
[0, 0, 0],
[1, 0, 0],
[0, 1, 0]]
但是我收到的模型的预测答案是浮动的:
[[0.3534753, 0.4548116, 0.1917132],
[0.3060284, 0.5562349, 0.1377369],
[0.2464814, 0.6586764, 0.094842 ],
[0.321316 , 0.5279192, 0.1507648],
[0.3391353, 0.4934992, 0.1673654]]
你能帮我理解这是正确的方法还是我的设置有错误?
2。我是否正确地将 One Hot 转换回 Tensor 和
decodedPred = tf.argMax(preds, axis=1)
Link 到行 https://github.com/webjema/TF-PH-AB-SIGMOID/blob/master/script.js#L67
3。一般来说,数据 and/or 模型设置中有什么大错误吗? 找不到 tf.js 示例来 class 将 n 个输入验证为一个 class(其中 n > 1).
此测试项目在 GitHub - https://github.com/webjema/TF-PH-AB-SIGMOID(带有 Docker 以便于检查)。
主要脚本:
async function getHealthData() {
const healthDataReq = await fetch('healthData.json');
const healthData = await healthDataReq.json();
const cleanedHealthData = healthData.map(d => ({
featureA: d.A,
featureB: d.B,
label: d.Class
})).filter(d => (d.featureA != null && d.featureB != null && d.label != null));
return cleanedHealthData;
}
async function getTestData() {
const testDataReq = await fetch('testData.json');
const testData = await testDataReq.json();
const cleanedTestData = testData.map(d => ({
featureA: d.A,
featureB: d.B
})).filter(d => (d.featureA != null && d.featureB != null));
return cleanedTestData;
}
function createModel() {
// Create a sequential model
const model = tf.sequential();
// Add an input layer
model.add(tf.layers.dense({ inputShape: [2], units: 1, useBias: true }));
model.add(tf.layers.dense({ units: 15, activation: 'relu' }));
model.add(tf.layers.dense({ units: 10, activation: 'relu' }));
// Add an output layer
model.add(tf.layers.dense({ units: 3, activation: 'softmax' }));
return model;
}
async function trainModel(model, inputs, labels) {
// Prepare the model for training.
model.compile({
optimizer: tf.train.adam(),
loss: tf.losses.meanSquaredError, //categorical_crossentropy? how?
metrics: ['acc'],
});
const batchSize = 10;
const epochs = 140;
const oneHot = tf.oneHot(labels, 3);
console.log("Train input:"); inputs.print();
console.log("Labels oneHot:"); oneHot.print(); // debug
return await model.fit(inputs, oneHot, {
batchSize,
epochs,
shuffle: true,
callbacks: tfvis.show.fitCallbacks(
{ name: 'Training Performance' },
['loss', 'label'],
{ height: 200, callbacks: ['onEpochEnd'] }
)
});
}
function testModel(model, inputData, min, max) {
const { inputs, labels } = inputData;
const unNormInput = inputs
.mul(max.sub(min))
.add(min);
console.log("Test data:");unNormInput.print(); // debug
const preds = model.predict(inputs);
console.log("Predict:"); preds.print(); // debug
decodedPred = tf.argMax(preds, axis=1);
console.log("Decoded Predict:"); decodedPred.print(); // debug
const decodedPredArray = decodedPred.arraySync();
// show output data table
const headers = ['Feature A', 'Feature B', 'Pred-Class'];
const values = unNormInput.arraySync().map((e, i) => e.concat(decodedPredArray[i]));
const surface = { name: 'Output health data table', tab: 'Data analisys' };
tfvis.render.table(surface, { headers, values });
}
async function run() {
// Load and plot the original input data that we are going to train on.
const healthData = await getHealthData();
const testData = await getTestData();
const { min, max } = getMinMax(healthData, testData);
// show input data table
const headers = ['Feature A', 'Feature B', 'Class'];
const values = healthData.map(d => [d.featureA, d.featureB, d.label]);
const surface = { name: 'Input health data table', tab: 'Data analisys' };
tfvis.render.table(surface, { headers, values });
// Create the model
const model = createModel();
tfvis.show.modelSummary({ name: 'Model Summary' }, model);
// Convert the data to a form we can use for training.
const { inputs, labels } = convertToTensor(healthData, min, max);
// Train the model
await trainModel(model, inputs, labels);
console.log('Done Training');
// Test model
const testTensorData = convertToTensor(testData, min, max);
testModel(model, testTensorData, min, max);
console.log('Done Testing');
}
document.addEventListener('DOMContentLoaded', run);
/**
* Convert the input data to tensors that we can use for machine
* learning. We will also do the important best practices of _shuffling_
* the data and _normalizing_ the data
*/
function convertToTensor(data, min, max) {
// Wrapping these calculations in a tidy will dispose any
// intermediate tensors.
// Step 1. Shuffle the data
tf.util.shuffle(data);
// Step 2. Convert data to Tensor
const inputs = data.map(d => [d.featureA, d.featureB])
const labels = data.map(d => d.label);
const inputTensor = tf.tensor2d(inputs, [inputs.length, 2]);
const normalizedInputs = inputTensor.sub(min).div(max.sub(min));
return {
inputs: normalizedInputs,
labels: labels
}
}
function getMinMax(healthData, testData) {
const inputs1 = healthData.map(d => [d.featureA, d.featureB])
const inputs2 = testData.map(d => [d.featureA, d.featureB])
const all = inputs1.concat(inputs2);
const inputTensor = tf.tensor2d(all, [all.length, 2]);
const inputMax = inputTensor.max();
const inputMin = inputTensor.min();
return { min: inputMin, max: inputMax }
}
对于模型设置,我使用了 https://stackabuse.com/tensorflow-2-0-solving-classification-and-regression-problems/
中的提示
你把它们转成一个hot的时候标签有很大错误
const oneHot = tf.oneHot(labels, 3);
因为您的 class 标签 https://i.stack.imgur.com/XYKAn.png 值为 [-1, 0 , 1]。我做一个快速测试。如果标签是 [ 0, 1, 2],tf.one_hot
给出您所期望的:
lables = [0, 1, 2]
depth = 3
tf.one_hot(lables , depth)
<tf.Tensor: shape=(3, 3), dtype=float32, numpy=
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]], dtype=float32)>
但是,如果您的 class 标签是 [-1,0 , 1]。你的一热转换会出错
labels = [-1, 0, 1]
depth = 3
tf.one_hot(labels, depth)
<tf.Tensor: shape=(3, 3), dtype=float32, numpy=
array([[0., 0., 0.],
[1., 0., 0.],
[0., 1., 0.]], dtype=float32)>
你的损失函数有误
你class一个热标签的化,你需要使用categorical_crossentropy
解决这 2 个问题应该会开始给你合理的结果
我正在尝试在 Tensorflow.js 中构建模型以 class 验证 2 个特征。
Input (training) data screenshot for clarity <- "Class" 有 A 和 B 特征输入的标签。
我的结果如下所示: Results where "Pred-Class" is predicted by model
因此,根据结果,我想向社区询问下一个问题:
1. 我正在为模型提供下一个张量 classification 的 One Hot 值:
[[0, 1, 0],
[0, 0, 0],
[0, 0, 0],
[1, 0, 0],
[0, 1, 0]]
但是我收到的模型的预测答案是浮动的:
[[0.3534753, 0.4548116, 0.1917132],
[0.3060284, 0.5562349, 0.1377369],
[0.2464814, 0.6586764, 0.094842 ],
[0.321316 , 0.5279192, 0.1507648],
[0.3391353, 0.4934992, 0.1673654]]
你能帮我理解这是正确的方法还是我的设置有错误?
2。我是否正确地将 One Hot 转换回 Tensor 和
decodedPred = tf.argMax(preds, axis=1)
Link 到行 https://github.com/webjema/TF-PH-AB-SIGMOID/blob/master/script.js#L67
3。一般来说,数据 and/or 模型设置中有什么大错误吗? 找不到 tf.js 示例来 class 将 n 个输入验证为一个 class(其中 n > 1).
此测试项目在 GitHub - https://github.com/webjema/TF-PH-AB-SIGMOID(带有 Docker 以便于检查)。
主要脚本:
async function getHealthData() {
const healthDataReq = await fetch('healthData.json');
const healthData = await healthDataReq.json();
const cleanedHealthData = healthData.map(d => ({
featureA: d.A,
featureB: d.B,
label: d.Class
})).filter(d => (d.featureA != null && d.featureB != null && d.label != null));
return cleanedHealthData;
}
async function getTestData() {
const testDataReq = await fetch('testData.json');
const testData = await testDataReq.json();
const cleanedTestData = testData.map(d => ({
featureA: d.A,
featureB: d.B
})).filter(d => (d.featureA != null && d.featureB != null));
return cleanedTestData;
}
function createModel() {
// Create a sequential model
const model = tf.sequential();
// Add an input layer
model.add(tf.layers.dense({ inputShape: [2], units: 1, useBias: true }));
model.add(tf.layers.dense({ units: 15, activation: 'relu' }));
model.add(tf.layers.dense({ units: 10, activation: 'relu' }));
// Add an output layer
model.add(tf.layers.dense({ units: 3, activation: 'softmax' }));
return model;
}
async function trainModel(model, inputs, labels) {
// Prepare the model for training.
model.compile({
optimizer: tf.train.adam(),
loss: tf.losses.meanSquaredError, //categorical_crossentropy? how?
metrics: ['acc'],
});
const batchSize = 10;
const epochs = 140;
const oneHot = tf.oneHot(labels, 3);
console.log("Train input:"); inputs.print();
console.log("Labels oneHot:"); oneHot.print(); // debug
return await model.fit(inputs, oneHot, {
batchSize,
epochs,
shuffle: true,
callbacks: tfvis.show.fitCallbacks(
{ name: 'Training Performance' },
['loss', 'label'],
{ height: 200, callbacks: ['onEpochEnd'] }
)
});
}
function testModel(model, inputData, min, max) {
const { inputs, labels } = inputData;
const unNormInput = inputs
.mul(max.sub(min))
.add(min);
console.log("Test data:");unNormInput.print(); // debug
const preds = model.predict(inputs);
console.log("Predict:"); preds.print(); // debug
decodedPred = tf.argMax(preds, axis=1);
console.log("Decoded Predict:"); decodedPred.print(); // debug
const decodedPredArray = decodedPred.arraySync();
// show output data table
const headers = ['Feature A', 'Feature B', 'Pred-Class'];
const values = unNormInput.arraySync().map((e, i) => e.concat(decodedPredArray[i]));
const surface = { name: 'Output health data table', tab: 'Data analisys' };
tfvis.render.table(surface, { headers, values });
}
async function run() {
// Load and plot the original input data that we are going to train on.
const healthData = await getHealthData();
const testData = await getTestData();
const { min, max } = getMinMax(healthData, testData);
// show input data table
const headers = ['Feature A', 'Feature B', 'Class'];
const values = healthData.map(d => [d.featureA, d.featureB, d.label]);
const surface = { name: 'Input health data table', tab: 'Data analisys' };
tfvis.render.table(surface, { headers, values });
// Create the model
const model = createModel();
tfvis.show.modelSummary({ name: 'Model Summary' }, model);
// Convert the data to a form we can use for training.
const { inputs, labels } = convertToTensor(healthData, min, max);
// Train the model
await trainModel(model, inputs, labels);
console.log('Done Training');
// Test model
const testTensorData = convertToTensor(testData, min, max);
testModel(model, testTensorData, min, max);
console.log('Done Testing');
}
document.addEventListener('DOMContentLoaded', run);
/**
* Convert the input data to tensors that we can use for machine
* learning. We will also do the important best practices of _shuffling_
* the data and _normalizing_ the data
*/
function convertToTensor(data, min, max) {
// Wrapping these calculations in a tidy will dispose any
// intermediate tensors.
// Step 1. Shuffle the data
tf.util.shuffle(data);
// Step 2. Convert data to Tensor
const inputs = data.map(d => [d.featureA, d.featureB])
const labels = data.map(d => d.label);
const inputTensor = tf.tensor2d(inputs, [inputs.length, 2]);
const normalizedInputs = inputTensor.sub(min).div(max.sub(min));
return {
inputs: normalizedInputs,
labels: labels
}
}
function getMinMax(healthData, testData) {
const inputs1 = healthData.map(d => [d.featureA, d.featureB])
const inputs2 = testData.map(d => [d.featureA, d.featureB])
const all = inputs1.concat(inputs2);
const inputTensor = tf.tensor2d(all, [all.length, 2]);
const inputMax = inputTensor.max();
const inputMin = inputTensor.min();
return { min: inputMin, max: inputMax }
}
对于模型设置,我使用了 https://stackabuse.com/tensorflow-2-0-solving-classification-and-regression-problems/
中的提示你把它们转成一个hot的时候标签有很大错误
const oneHot = tf.oneHot(labels, 3);
因为您的 class 标签 https://i.stack.imgur.com/XYKAn.png 值为 [-1, 0 , 1]。我做一个快速测试。如果标签是 [ 0, 1, 2],tf.one_hot
给出您所期望的:
lables = [0, 1, 2]
depth = 3
tf.one_hot(lables , depth)
<tf.Tensor: shape=(3, 3), dtype=float32, numpy=
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]], dtype=float32)>
但是,如果您的 class 标签是 [-1,0 , 1]。你的一热转换会出错
labels = [-1, 0, 1]
depth = 3
tf.one_hot(labels, depth)
<tf.Tensor: shape=(3, 3), dtype=float32, numpy=
array([[0., 0., 0.],
[1., 0., 0.],
[0., 1., 0.]], dtype=float32)>
你的损失函数有误
你class一个热标签的化,你需要使用categorical_crossentropy
解决这 2 个问题应该会开始给你合理的结果