js实现“大模型”之明星识别(三),数据集划分和模型调参和选择

278 阅读11分钟

PS:点赞,评论,收藏,分享 防止迷路

接上一篇文章 # js实现“大模型”之明星识别(二),保存/加载训练模型和数据集

在机器学习和深度学习项目中,将数据集分为训练集和验证集(有时还包括测试集)是非常重要的步骤。这样做有助于提高模型的泛化能力和防止过拟合。以下是关于训练集和验证集的详细说明:

一 数据集分类

训练集(Training Set)

  • 目的:用于训练模型,让模型学习数据中的模式和特征。
  • 特点:通常占整个数据集的大部分(例如70%到80%)。
  • 作用:模型通过训练集调整其参数以最小化训练误差。

验证集(Validation Set)

  • 目的:用于调整模型的超参数和选择最佳模型。
  • 特点:通常占整个数据集的一部分(例如10%到15%)。
  • 作用:帮助选择最优的模型配置,避免过拟合。通过验证集评估模型在未见过的数据上的表现。

测试集(Test Set)

  • 目的:用于最终评估模型的性能。
  • 特点:通常占整个数据集的剩余部分(例如10%到15%)。
  • 作用:提供一个独立的评估指标,确保模型在实际应用中的表现符合预期。

分割数据集的步骤

  1. 收集数据:首先收集所有可用的数据。
  2. 预处理数据:清洗和准备数据,包括处理缺失值、归一化、编码分类变量等。
  3. 分割数据集:将数据集分为训练集、验证集和测试集。

示例代码:分割数据集

以下是如何使用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}`);

解释

  1. 数据准备:首先准备原始数据,并将其转换为数值特征。
  2. 打乱数据:为了确保数据的随机性,打乱数据顺序。
  3. 分割数据集:根据比例将数据分割为训练集、验证集和测试集。
  4. 保存数据:将每个数据集保存到单独的文件中。
  5. 训练模型:使用训练集训练模型。
  6. 评估模型:使用验证集和测试集评估模型的性能。

通过这种方式,你可以有效地管理数据集,并确保模型在不同数据上的表现一致且可靠。

二 模型参数调整和模型选择

调整模型参数是优化机器学习模型性能的重要步骤。不同的模型有不同的参数,但常见的参数包括学习率、迭代次数、隐藏层大小等。以下是一些常见的模型参数及其调整方法,以及如何在 brain.js 中调整这些参数的示例。

常见的模型参数

  1. 学习率(Learning Rate)

    • 作用:控制模型在每次迭代中更新权重的速度。
    • 调整建议:较高的学习率可能导致模型不稳定,而较低的学习率可能导致收敛速度慢。通常从一个中等值开始,然后根据模型的表现进行微调。
  2. 迭代次数(Iterations)

    • 作用:控制模型训练的总次数。
    • 调整建议:更多的迭代次数可能会提高模型的性能,但也可能导致过拟合。可以通过观察验证集的性能来确定最佳迭代次数。
  3. 隐藏层大小(Hidden Layer Size)

    • 作用:控制神经网络中隐藏层的神经元数量。
    • 调整建议:较大的隐藏层可以捕捉更复杂的模式,但也可能导致过拟合。通常需要通过实验找到最佳的隐藏层大小。
  4. 误差阈值(Error Threshold)

    • 作用:设置模型训练的误差阈值,当训练误差低于该阈值时停止训练。
    • 调整建议:较低的误差阈值可能导致模型训练时间增加,而较高的误差阈值可能导致模型性能下降。
  5. 批处理大小(Batch Size)

    • 作用:控制每次更新权重时使用的样本数量。
    • 调整建议:较大的批处理大小可以提高训练效率,但需要更多的内存。较小的批处理大小可以提供更好的梯度估计,但可能导致训练不稳定。

调整参数的步骤

  1. 定义初始参数:选择一组合理的初始参数。
  2. 训练模型:使用初始参数训练模型。
  3. 评估模型:使用验证集评估模型的性能。
  4. 调整参数:根据评估结果调整参数。
  5. 重复训练和评估:重复上述步骤,直到找到最佳参数组合。

示例代码:调整 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}`);

解释

  1. 定义初始参数:设置了初始的隐藏层大小、学习率、误差阈值、迭代次数等参数。
  2. 训练模型:使用初始参数训练模型。
  3. 评估模型:使用验证集和测试集评估模型的性能。
  4. 调整参数:根据评估结果调整参数,例如降低误差阈值、增加迭代次数、调整学习率等。
  5. 重新训练和评估:使用调整后的参数重新训练模型,并再次评估其性能。

通过这种方式,你可以逐步优化模型的参数,提高模型的性能和泛化能力。

在调整好模型的最佳参数并完成训练后,你需要对模型进行保存、评估和部署。以下是详细的步骤和注意事项:

三 保存模型&部署模型

保存模型是为了能够在后续使用中加载和重用,而不需要重新训练。这可以节省时间和计算资源。

示例代码:保存模型

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}`);
});

监控和维护 在模型部署后,持续监控模型的性能是非常重要的。如果模型的性能下降,可能需要重新训练或调整参数。

监控和维护的建议

  • 定期评估:定期使用新的数据集评估模型的性能。
  • 日志记录:记录模型的预测结果和实际结果,以便分析和调试。
  • 反馈机制:建立用户反馈机制,收集用户的反馈信息,用于改进模型。
  • 自动更新:考虑实现自动化的模型更新流程,当新的数据可用时自动重新训练和部署模型。

总结

  1. 保存模型:将训练好的模型保存到文件中,以便后续使用。
  2. 评估模型:使用验证集和测试集评估模型的性能,确保模型在实际应用中的表现良好。
  3. 部署模型:将模型集成到实际的应用系统中,使其能够处理实时数据或批量数据。
  4. 监控和维护:持续监控模型的性能,定期评估和更新模型,确保其长期稳定运行。

通过这些步骤,你可以确保模型在实际应用中表现出色,并能够及时应对可能出现的问题。

PS:创作不易 学会了记得,点赞,评论,收藏,分享

作者:AndyGoWei
链接:juejin.cn/post/744624…
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。