PS:点赞,评论,收藏,分享 防止迷路
接上一篇文章 # js实现“大模型”之明星识别(二),保存/加载训练模型和数据集
在机器学习和深度学习项目中,将数据集分为训练集和验证集(有时还包括测试集)是非常重要的步骤。这样做有助于提高模型的泛化能力和防止过拟合。以下是关于训练集和验证集的详细说明:
一 数据集分类
训练集(Training Set)
- 目的:用于训练模型,让模型学习数据中的模式和特征。
- 特点:通常占整个数据集的大部分(例如70%到80%)。
- 作用:模型通过训练集调整其参数以最小化训练误差。
验证集(Validation Set)
- 目的:用于调整模型的超参数和选择最佳模型。
- 特点:通常占整个数据集的一部分(例如10%到15%)。
- 作用:帮助选择最优的模型配置,避免过拟合。通过验证集评估模型在未见过的数据上的表现。
测试集(Test Set)
- 目的:用于最终评估模型的性能。
- 特点:通常占整个数据集的剩余部分(例如10%到15%)。
- 作用:提供一个独立的评估指标,确保模型在实际应用中的表现符合预期。
分割数据集的步骤
- 收集数据:首先收集所有可用的数据。
- 预处理数据:清洗和准备数据,包括处理缺失值、归一化、编码分类变量等。
- 分割数据集:将数据集分为训练集、验证集和测试集。
示例代码:分割数据集
以下是如何使用JavaScript和brain.js库分割数据集的示例:
javascript
代码解读
复制代码
const brain = require("brain.js");
const fs = require('fs');
// 定义明星的名字和对应的标签
const stars = ["刘德华", "张学友", "郭富城"];
// 创建一个新的神经网络实例,禁用 GPU 加速
const net = new brain.NeuralNetwork({
gpu: false,
});
// 定义特征词典
const featureDictionary = {
高鼻梁: [1, 0, 0],
大眼睛: [0, 1, 0],
小眼睛: [0, 0, 1],
短发: [1, 0, 0],
长发: [0, 1, 0],
圆脸: [0, 0, 1],
方脸: [1, 0, 0],
尖下巴: [0, 1, 0],
厚嘴唇: [0, 0, 1],
// 可以根据需要添加更多特征
};
// 将文本描述转换为数值特征
function textToFeatures(text) {
const features = [0, 0, 0, 0, 0, 0, 0, 0]; // 初始化特征向量
const words = text.split(" ");
words.forEach((word) => {
if (featureDictionary[word]) {
featureDictionary[word].forEach((value, index) => {
features[index] += value;
});
}
});
return features;
}
// 准备原始数据
const rawData = [
{ input: "高鼻梁 大眼睛", output: [1, 0, 0] }, // 刘德华
{ input: "高鼻梁 小眼睛", output: [0, 1, 0] }, // 张学友
{ input: "短发 圆脸", output: [0, 0, 1] }, // 郭富城
{ input: "长发 方脸", output: [1, 0, 0] }, // 刘德华
{ input: "尖下巴 厚嘴唇", output: [0, 1, 0] }, // 张学友
{ input: "高鼻梁 短发", output: [0, 0, 1] }, // 郭富城
// 添加更多数据
];
// 将文本输入转换为数值特征
const data = rawData.map(item => ({
input: textToFeatures(item.input),
output: item.output
}));
// 打乱数据顺序
data.sort(() => Math.random() - 0.5);
// 计算分割点
const trainSize = Math.floor(data.length * 0.7);
const validationSize = Math.floor(data.length * 0.15);
const testSize = data.length - trainSize - validationSize;
// 分割数据集
const trainingData = data.slice(0, trainSize);
const validationData = data.slice(trainSize, trainSize + validationSize);
const testData = data.slice(trainSize + validationSize);
// 保存训练数据到文件
fs.writeFileSync('trainingData.json', JSON.stringify(trainingData));
fs.writeFileSync('validationData.json', JSON.stringify(validationData));
fs.writeFileSync('testData.json', JSON.stringify(testData));
// 训练神经网络
net.train(trainingData, {
errorThresh: 0.005, // error threshold to reach
iterations: 20000, // maximum training iterations
log: true, // console.log() progress periodically
logPeriod: 10, // number of iterations between logging
learningRate: 0.3, // learning rate
});
// 保存训练好的模型
const json = net.toJSON();
fs.writeFileSync('model.json', JSON.stringify(json));
// 使用验证集评估模型
const validationAccuracy = net.test(validationData);
console.log(`验证集准确率: ${validationAccuracy}`);
// 使用测试集评估模型
const testAccuracy = net.test(testData);
console.log(`测试集准确率: ${testAccuracy}`);
解释
- 数据准备:首先准备原始数据,并将其转换为数值特征。
- 打乱数据:为了确保数据的随机性,打乱数据顺序。
- 分割数据集:根据比例将数据分割为训练集、验证集和测试集。
- 保存数据:将每个数据集保存到单独的文件中。
- 训练模型:使用训练集训练模型。
- 评估模型:使用验证集和测试集评估模型的性能。
通过这种方式,你可以有效地管理数据集,并确保模型在不同数据上的表现一致且可靠。
二 模型参数调整和模型选择
调整模型参数是优化机器学习模型性能的重要步骤。不同的模型有不同的参数,但常见的参数包括学习率、迭代次数、隐藏层大小等。以下是一些常见的模型参数及其调整方法,以及如何在 brain.js 中调整这些参数的示例。
常见的模型参数
-
学习率(Learning Rate)
- 作用:控制模型在每次迭代中更新权重的速度。
- 调整建议:较高的学习率可能导致模型不稳定,而较低的学习率可能导致收敛速度慢。通常从一个中等值开始,然后根据模型的表现进行微调。
-
迭代次数(Iterations)
- 作用:控制模型训练的总次数。
- 调整建议:更多的迭代次数可能会提高模型的性能,但也可能导致过拟合。可以通过观察验证集的性能来确定最佳迭代次数。
-
隐藏层大小(Hidden Layer Size)
- 作用:控制神经网络中隐藏层的神经元数量。
- 调整建议:较大的隐藏层可以捕捉更复杂的模式,但也可能导致过拟合。通常需要通过实验找到最佳的隐藏层大小。
-
误差阈值(Error Threshold)
- 作用:设置模型训练的误差阈值,当训练误差低于该阈值时停止训练。
- 调整建议:较低的误差阈值可能导致模型训练时间增加,而较高的误差阈值可能导致模型性能下降。
-
批处理大小(Batch Size)
- 作用:控制每次更新权重时使用的样本数量。
- 调整建议:较大的批处理大小可以提高训练效率,但需要更多的内存。较小的批处理大小可以提供更好的梯度估计,但可能导致训练不稳定。
调整参数的步骤
- 定义初始参数:选择一组合理的初始参数。
- 训练模型:使用初始参数训练模型。
- 评估模型:使用验证集评估模型的性能。
- 调整参数:根据评估结果调整参数。
- 重复训练和评估:重复上述步骤,直到找到最佳参数组合。
示例代码:调整 brain.js
以下是一个示例,展示了如何在 brain.js 中调整模型参数:
javascript
代码解读
复制代码
const brain = require("brain.js");
const fs = require('fs');
// 定义明星的名字和对应的标签
const stars = ["刘德华", "张学友", "郭富城"];
// 创建一个新的神经网络实例,禁用 GPU 加速
const net = new brain.NeuralNetwork({
hiddenLayers: [10], // 初始隐藏层大小
learningRate: 0.3, // 初始学习率
});
// 定义特征词典
const featureDictionary = {
高鼻梁: [1, 0, 0],
大眼睛: [0, 1, 0],
小眼睛: [0, 0, 1],
短发: [1, 0, 0],
长发: [0, 1, 0],
圆脸: [0, 0, 1],
方脸: [1, 0, 0],
尖下巴: [0, 1, 0],
厚嘴唇: [0, 0, 1],
// 可以根据需要添加更多特征
};
// 将文本描述转换为数值特征
function textToFeatures(text) {
const features = [0, 0, 0, 0, 0, 0, 0, 0]; // 初始化特征向量
const words = text.split(" ");
words.forEach((word) => {
if (featureDictionary[word]) {
featureDictionary[word].forEach((value, index) => {
features[index] += value;
});
}
});
return features;
}
// 准备原始数据
const rawData = [
{ input: "高鼻梁 大眼睛", output: [1, 0, 0] }, // 刘德华
{ input: "高鼻梁 小眼睛", output: [0, 1, 0] }, // 张学友
{ input: "短发 圆脸", output: [0, 0, 1] }, // 郭富城
{ input: "长发 方脸", output: [1, 0, 0] }, // 刘德华
{ input: "尖下巴 厚嘴唇", output: [0, 1, 0] }, // 张学友
{ input: "高鼻梁 短发", output: [0, 0, 1] }, // 郭富城
// 添加更多数据
];
// 将文本输入转换为数值特征
const data = rawData.map(item => ({
input: textToFeatures(item.input),
output: item.output
}));
// 打乱数据顺序
data.sort(() => Math.random() - 0.5);
// 计算分割点
const trainSize = Math.floor(data.length * 0.7);
const validationSize = Math.floor(data.length * 0.15);
const testSize = data.length - trainSize - validationSize;
// 分割数据集
const trainingData = data.slice(0, trainSize);
const validationData = data.slice(trainSize, trainSize + validationSize);
const testData = data.slice(trainSize + validationSize);
// 保存训练数据到文件
fs.writeFileSync('trainingData.json', JSON.stringify(trainingData));
fs.writeFileSync('validationData.json', JSON.stringify(validationData));
fs.writeFileSync('testData.json', JSON.stringify(testData));
// 定义初始训练参数
const initialParams = {
errorThresh: 0.005, // 初始误差阈值
iterations: 20000, // 初始迭代次数
log: true, // 是否记录日志
logPeriod: 10, // 日志记录间隔
learningRate: 0.3, // 初始学习率
};
// 训练神经网络
net.train(trainingData, initialParams);
// 保存训练好的模型
const json = net.toJSON();
fs.writeFileSync('model.json', JSON.stringify(json));
// 使用验证集评估模型
const validationAccuracy = net.test(validationData);
console.log(`验证集准确率: ${validationAccuracy}`);
// 使用测试集评估模型
const testAccuracy = net.test(testData);
console.log(`测试集准确率: ${testAccuracy}`);
// 调整参数
const adjustedParams = {
errorThresh: 0.001, // 更低的误差阈值
iterations: 30000, // 更多的迭代次数
log: true, // 是否记录日志
logPeriod: 10, // 日志记录间隔
learningRate: 0.1, // 更低的学习率
};
// 重新训练神经网络
net.train(trainingData, adjustedParams);
// 保存调整后的模型
const adjustedJson = net.toJSON();
fs.writeFileSync('adjustedModel.json', JSON.stringify(adjustedJson));
// 使用验证集评估调整后的模型
const adjustedValidationAccuracy = net.test(validationData);
console.log(`调整后的验证集准确率: ${adjustedValidationAccuracy}`);
// 使用测试集评估调整后的模型
const adjustedTestAccuracy = net.test(testData);
console.log(`调整后的测试集准确率: ${adjustedTestAccuracy}`);
解释
- 定义初始参数:设置了初始的隐藏层大小、学习率、误差阈值、迭代次数等参数。
- 训练模型:使用初始参数训练模型。
- 评估模型:使用验证集和测试集评估模型的性能。
- 调整参数:根据评估结果调整参数,例如降低误差阈值、增加迭代次数、调整学习率等。
- 重新训练和评估:使用调整后的参数重新训练模型,并再次评估其性能。
通过这种方式,你可以逐步优化模型的参数,提高模型的性能和泛化能力。
在调整好模型的最佳参数并完成训练后,你需要对模型进行保存、评估和部署。以下是详细的步骤和注意事项:
三 保存模型&部署模型
保存模型是为了能够在后续使用中加载和重用,而不需要重新训练。这可以节省时间和计算资源。
示例代码:保存模型
javascript
代码解读
复制代码
const brain = require("brain.js");
const fs = require('fs');
// 创建一个新的神经网络实例
const net = new brain.NeuralNetwork();
// 训练数据
const trainingData = [
{ input: [0, 0], output: [0] },
{ input: [0, 1], output: [1] },
{ input: [1, 0], output: [1] },
{ input: [1, 1], output: [0] }
];
// 训练模型
net.train(trainingData, {
errorThresh: 0.005, // 误差阈值
iterations: 20000, // 最大迭代次数
log: true, // 是否记录日志
logPeriod: 10, // 日志记录间隔
learningRate: 0.3 // 学习率
});
// 保存模型
const modelJson = net.toJSON();
fs.writeFileSync('model.json', JSON.stringify(modelJson));
console.log("模型已保存到 model.json");
评估模型 评估模型的性能是确保模型在实际应用中表现良好的关键步骤。通常使用验证集和测试集进行评估。
示例代码:评估模型
javascript
代码解读
复制代码
// 加载模型
const modelJson = fs.readFileSync('model.json', 'utf8');
const net = new brain.NeuralNetwork();
net.fromJSON(JSON.parse(modelJson));
// 验证数据
const validationData = [
{ input: [0, 0], output: [0] },
{ input: [0, 1], output: [1] },
{ input: [1, 0], output: [1] },
{ input: [1, 1], output: [0] }
];
// 测试数据
const testData = [
{ input: [0, 0], output: [0] },
{ input: [0, 1], output: [1] },
{ input: [1, 0], output: [1] },
{ input: [1, 1], output: [0] }
];
// 评估验证集
const validationAccuracy = net.test(validationData);
console.log(`验证集准确率: ${validationAccuracy}`);
// 评估测试集
const testAccuracy = net.test(testData);
console.log(`测试集准确率: ${testAccuracy}`);
部署模型 部署模型是指将模型集成到实际的应用系统中,使其能够处理实时数据或批量数据。
示例代码:部署模型 假设你有一个简单的Web应用,使用Express框架来处理HTTP请求。
javascript
代码解读
复制代码
const express = require('express');
const fs = require('fs');
const brain = require('brain.js');
// 创建Express应用
const app = express();
app.use(express.json());
// 加载模型
const modelJson = fs.readFileSync('model.json', 'utf8');
const net = new brain.NeuralNetwork();
net.fromJSON(JSON.parse(modelJson));
// 定义预测路由
app.post('/predict', (req, res) => {
const input = req.body.input; // 输入数据
const output = net.run(input); // 进行预测
res.json({ output });
});
// 启动服务器
const PORT = 3000;
app.listen(PORT, () => {
console.log(`服务器运行在 http://localhost:${PORT}`);
});
监控和维护 在模型部署后,持续监控模型的性能是非常重要的。如果模型的性能下降,可能需要重新训练或调整参数。
监控和维护的建议
- 定期评估:定期使用新的数据集评估模型的性能。
- 日志记录:记录模型的预测结果和实际结果,以便分析和调试。
- 反馈机制:建立用户反馈机制,收集用户的反馈信息,用于改进模型。
- 自动更新:考虑实现自动化的模型更新流程,当新的数据可用时自动重新训练和部署模型。
总结
- 保存模型:将训练好的模型保存到文件中,以便后续使用。
- 评估模型:使用验证集和测试集评估模型的性能,确保模型在实际应用中的表现良好。
- 部署模型:将模型集成到实际的应用系统中,使其能够处理实时数据或批量数据。
- 监控和维护:持续监控模型的性能,定期评估和更新模型,确保其长期稳定运行。
通过这些步骤,你可以确保模型在实际应用中表现出色,并能够及时应对可能出现的问题。
PS:创作不易 学会了记得,点赞,评论,收藏,分享
作者:AndyGoWei
链接:juejin.cn/post/744624…
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。