第4章:机器学习基础

4.1 机器学习核心概念

理论讲解

机器学习是人工智能的一个分支,它使计算机能够从数据中学习并改进性能,而无需显式编程。以下是机器学习的核心概念:

  • 数据:机器学习的基础,包括特征和标签
  • 特征:数据的属性或特性,用于描述数据
  • 标签:数据的输出或结果,用于监督学习
  • 模型:从数据中学习的算法或函数
  • 训练:使用数据调整模型参数的过程
  • 测试:评估模型性能的过程
  • 泛化:模型对新数据的适应能力
  • 过拟合:模型在训练数据上表现很好,但在新数据上表现差
  • 欠拟合:模型在训练数据和新数据上都表现差

机器学习算法通常分为三类:监督学习、无监督学习和强化学习。

代码示例

// 机器学习核心概念的简单演示
class SimpleModel {
  constructor() {
    this.weight = 0;
    this.bias = 0;
  }
  
  // 预测函数:y = wx + b
  predict(x) {
    return this.weight * x + this.bias;
  }
  
  // 训练函数:使用最小二乘法更新参数
  train(xs, ys, epochs = 100, learningRate = 0.01) {
    for (let epoch = 0; epoch < epochs; epoch++) {
      let totalError = 0;
      
      for (let i = 0; i < xs.length; i++) {
        const x = xs[i];
        const y = ys[i];
        const prediction = this.predict(x);
        const error = y - prediction;
        
        // 更新权重和偏置
        this.weight += learningRate * error * x;
        this.bias += learningRate * error;
        
        totalError += Math.abs(error);
      }
      
      if (epoch % 10 === 0) {
        console.log(`Epoch ${epoch}: Average Error = ${totalError / xs.length}`);
      }
    }
  }
}

// 使用示例
const model = new SimpleModel();
const xs = [1, 2, 3, 4, 5];
const ys = [2, 4, 6, 8, 10]; // y = 2x

console.log('Before training:');
console.log(`f(3) = ${model.predict(3)}`); // 应该接近6

model.train(xs, ys);

console.log('After training:');
console.log(`f(3) = ${model.predict(3)}`); // 应该接近6
console.log(`Weight: ${model.weight}, Bias: ${model.bias}`);

实践练习

  1. 运行上面的代码,观察模型训练过程
  2. 修改训练数据,使y = 3x + 1,重新训练模型
  3. 尝试不同的学习率和迭代次数,观察对训练结果的影响
  4. 预测一个新的x值,如x=6,检查结果是否接近预期

4.2 监督学习与无监督学习

理论讲解

监督学习是最常见的机器学习类型,它使用带有标签的数据进行训练。主要包括:

  • 分类:预测离散的类别标签,如垃圾邮件检测、图像分类等
  • 回归:预测连续的数值,如房价预测、股票价格预测等
  • 序列预测:预测时间序列数据,如天气预测、销售额预测等

无监督学习使用没有标签的数据进行训练,主要包括:

  • 聚类:将相似的数据点分组,如客户细分、图像聚类等
  • 降维:减少数据的维度,同时保留关键信息,如PCA、t-SNE等
  • 关联规则学习:发现数据中的关联关系,如购物篮分析

强化学习是一种特殊的机器学习类型,它通过与环境交互来学习最优策略。

代码示例

// 监督学习与无监督学习的简单演示

// 监督学习:分类示例
function supervisedClassification() {
  console.log('=== 监督学习:分类示例 ===');
  
  // 训练数据:带有标签
  const trainingData = [
    { features: [1, 2], label: 'A' },
    { features: [2, 3], label: 'A' },
    { features: [3, 1], label: 'B' },
    { features: [4, 2], label: 'B' }
  ];
  
  console.log('训练数据:', trainingData);
  console.log('模型:根据特征预测类别标签');
}

// 无监督学习:聚类示例
function unsupervisedClustering() {
  console.log('\n=== 无监督学习:聚类示例 ===');
  
  // 训练数据:没有标签
  const trainingData = [
    { features: [1, 2] },
    { features: [2, 3] },
    { features: [3, 1] },
    { features: [4, 2] }
  ];
  
  console.log('训练数据:', trainingData);
  console.log('模型:将相似的数据点分组');
}

// 运行演示
supervisedClassification();
unsupervisedClustering();

实践练习

  1. 描述一个你身边的监督学习应用场景
  2. 描述一个你身边的无监督学习应用场景
  3. 思考:为什么有些问题适合监督学习,而有些适合无监督学习?

4.3 模型训练流程

理论讲解

一个完整的机器学习模型训练流程包括以下步骤:

  1. 问题定义:明确要解决的问题和目标
  2. 数据收集:获取相关的数据
  3. 数据预处理:清洗、转换和标准化数据
  4. 特征工程:选择和提取有用的特征
  5. 模型选择:选择适合问题的机器学习算法
  6. 模型训练:使用训练数据调整模型参数
  7. 模型评估:使用测试数据评估模型性能
  8. 模型优化:调整超参数,改进模型性能
  9. 模型部署:将模型应用到实际场景中
  10. 模型监控:监控模型在生产环境中的性能

代码示例

// 模型训练流程的简单演示
function modelTrainingProcess() {
  console.log('=== 模型训练流程 ===');
  
  // 1. 问题定义
  console.log('1. 问题定义:预测房屋价格');
  
  // 2. 数据收集
  console.log('2. 数据收集:获取房屋面积和价格数据');
  const data = [
    { area: 100, price: 500000 },
    { area: 150, price: 750000 },
    { area: 200, price: 1000000 },
    { area: 250, price: 1250000 },
    { area: 300, price: 1500000 }
  ];
  
  // 3. 数据预处理
  console.log('3. 数据预处理:标准化数据');
  const maxArea = Math.max(...data.map(d => d.area));
  const maxPrice = Math.max(...data.map(d => d.price));
  const normalizedData = data.map(d => ({
    area: d.area / maxArea,
    price: d.price / maxPrice
  }));
  
  // 4. 特征工程
  console.log('4. 特征工程:选择面积作为特征');
  const xs = normalizedData.map(d => d.area);
  const ys = normalizedData.map(d => d.price);
  
  // 5. 模型选择
  console.log('5. 模型选择:使用线性回归模型');
  class LinearRegression {
    constructor() {
      this.weight = 0;
      this.bias = 0;
    }
    
    predict(x) {
      return this.weight * x + this.bias;
    }
    
    train(xs, ys, epochs = 100, lr = 0.01) {
      for (let epoch = 0; epoch < epochs; epoch++) {
        let error = 0;
        for (let i = 0; i < xs.length; i++) {
          const prediction = this.predict(xs[i]);
          const delta = ys[i] - prediction;
          this.weight += lr * delta * xs[i];
          this.bias += lr * delta;
          error += delta ** 2;
        }
        if (epoch % 20 === 0) {
          console.log(`  Epoch ${epoch}: MSE = ${error / xs.length}`);
        }
      }
    }
  }
  
  // 6. 模型训练
  console.log('6. 模型训练:使用训练数据训练模型');
  const model = new LinearRegression();
  model.train(xs, ys);
  
  // 7. 模型评估
  console.log('7. 模型评估:计算训练数据上的误差');
  let totalError = 0;
  for (let i = 0; i < xs.length; i++) {
    const prediction = model.predict(xs[i]);
    totalError += Math.abs(prediction - ys[i]);
  }
  console.log(`  Average Error: ${totalError / xs.length}`);
  
  // 8. 模型优化
  console.log('8. 模型优化:调整学习率和迭代次数');
  
  // 9. 模型部署
  console.log('9. 模型部署:将模型应用到实际场景');
  const newArea = 180 / maxArea; // 180平方米
  const predictedPrice = model.predict(newArea) * maxPrice;
  console.log(`  预测180平方米房屋价格:${predictedPrice.toFixed(2)}`);
  
  // 10. 模型监控
  console.log('10. 模型监控:监控模型在生产环境中的性能');
}

modelTrainingProcess();

实践练习

  1. 运行上面的代码,了解完整的模型训练流程
  2. 修改数据,添加更多特征,如房间数量、楼层等
  3. 尝试使用不同的学习率和迭代次数,观察对模型性能的影响
  4. 计算模型在测试数据上的性能指标

4.4 实战:训练简单分类模型

理论讲解

在这个实战中,我们将使用TensorFlow.js训练一个简单的分类模型,用于识别手写数字。我们将使用MNIST数据集,这是一个经典的手写数字数据集,包含60,000个训练样本和10,000个测试样本。

分类模型的训练流程包括:

  1. 加载和预处理数据
  2. 定义模型结构
  3. 编译模型
  4. 训练模型
  5. 评估模型
  6. 使用模型进行预测

代码示例

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>实战:训练简单分类模型</title>
    <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@4.10.0/dist/tf.min.js"></script>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
        }
        .container {
            text-align: center;
        }
        .output {
            background-color: #f5f5f5;
            padding: 10px;
            margin: 10px 0;
            border-radius: 4px;
            text-align: left;
            white-space: pre-wrap;
        }
        button {
            background-color: #4CAF50;
            color: white;
            border: none;
            padding: 10px 20px;
            font-size: 16px;
            border-radius: 4px;
            cursor: pointer;
            margin: 10px;
        }
        button:hover {
            background-color: #45a049;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>实战:训练简单分类模型</h1>
        <p>使用TensorFlow.js训练一个手写数字分类模型</p>
        
        <button onclick="runTraining()">开始训练</button>
        <div class="output" id="output"></div>
        
        <h3>预测示例</h3>
        <input type="number" id="testInput" min="0" max="9" value="5">
        <button onclick="runPrediction()">预测</button>
        <div id="predictionResult"></div>
    </div>

    <script>
        const outputDiv = document.getElementById('output');
        const predictionResultDiv = document.getElementById('predictionResult');
        let model;
        let testData;
        
        // 输出日志
        function log(message) {
            outputDiv.innerHTML += message + '\n';
            console.log(message);
        }
        
        // 加载MNIST数据集
        async function loadData() {
            log('加载MNIST数据集...');
            const mnist = await tf.data.webcam.mnist.load();
            return mnist;
        }
        
        // 预处理数据
        function preprocessData(data) {
            log('预处理数据...');
            // 将图像数据转换为0-1范围
            return data.map(item => ({
                xs: item.xs.div(255),
                ys: item.ys
            }));
        }
        
        // 定义模型
        function createModel() {
            log('定义模型结构...');
            const model = tf.sequential();
            
            // 添加输入层和卷积层
            model.add(tf.layers.conv2d({
                inputShape: [28, 28, 1],
                filters: 32,
                kernelSize: 3,
                activation: 'relu'
            }));
            
            // 添加池化层
            model.add(tf.layers.maxPooling2d({
                poolSize: 2, 
                strides: 2
            }));
            
            // 添加展平层
            model.add(tf.layers.flatten());
            
            // 添加全连接层
            model.add(tf.layers.dense({
                units: 128, 
                activation: 'relu'
            }));
            
            // 添加输出层
            model.add(tf.layers.dense({
                units: 10, 
                activation: 'softmax'
            }));
            
            return model;
        }
        
        // 编译模型
        function compileModel(model) {
            log('编译模型...');
            model.compile({
                optimizer: 'adam',
                loss: 'categoricalCrossentropy',
                metrics: ['accuracy']
            });
        }
        
        // 训练模型
        async function trainModel(model, trainData) {
            log('开始训练模型...');
            
            const history = await model.fit(
                trainData.xs,
                trainData.ys,
                {
                    epochs: 5,
                    batchSize: 32,
                    validationSplit: 0.2,
                    callbacks: {
                        onEpochEnd: (epoch, logs) => {
                            log(`Epoch ${epoch + 1}: 损失 = ${logs.loss.toFixed(4)}, 准确率 = ${logs.acc.toFixed(4)}, 验证损失 = ${logs.val_loss.toFixed(4)}, 验证准确率 = ${logs.val_acc.toFixed(4)}`);
                        }
                    }
                }
            );
            
            return history;
        }
        
        // 评估模型
        async function evaluateModel(model, testData) {
            log('评估模型...');
            const result = await model.evaluate(testData.xs, testData.ys);
            log(`测试损失: ${result[0].toFixed(4)}, 测试准确率: ${result[1].toFixed(4)}`);
            return result;
        }
        
        // 主训练函数
        async function runTraining() {
            outputDiv.innerHTML = '';
            
            // 1. 加载数据
            const mnistData = await loadData();
            const trainData = preprocessData(mnistData.train);
            testData = preprocessData(mnistData.test);
            
            // 2. 创建模型
            model = createModel();
            model.summary();
            
            // 3. 编译模型
            compileModel(model);
            
            // 4. 训练模型
            await trainModel(model, trainData);
            
            // 5. 评估模型
            await evaluateModel(model, testData);
            
            log('训练完成!');
        }
        
        // 使用模型进行预测
        async function runPrediction() {
            if (!model || !testData) {
                predictionResultDiv.innerHTML = '<p>请先训练模型!</p>';
                return;
            }
            
            const index = parseInt(document.getElementById('testInput').value);
            if (isNaN(index) || index < 0 || index >= testData.xs.shape[0]) {
                predictionResultDiv.innerHTML = '<p>请输入有效的索引!</p>';
                return;
            }
            
            // 获取测试样本
            const testSample = testData.xs.slice([index, 0, 0, 0], [1, 28, 28, 1]);
            const actualLabel = testData.ys.slice([index, 0], [1, 10]);
            
            // 进行预测
            const prediction = model.predict(testSample);
            const predictedLabel = tf.argMax(prediction, 1).dataSync()[0];
            const actualLabelValue = tf.argMax(actualLabel, 1).dataSync()[0];
            
            // 显示结果
            predictionResultDiv.innerHTML = `
                <h4>预测结果</h4>
                <p>实际标签:${actualLabelValue}</p>
                <p>预测标签:${predictedLabel}</p>
                <p>预测正确:${predictedLabel === actualLabelValue ? '是' : '否'}</p>
            `;
        }
    </script>
</body>
</html>

实践练习

  1. 运行上面的代码,训练一个手写数字分类模型
  2. 观察训练过程中的损失和准确率变化
  3. 使用不同的测试样本进行预测,观察模型性能
  4. 尝试修改模型结构,如添加更多卷积层或调整滤波器数量
  5. 调整训练参数,如批次大小、迭代次数等,观察对模型性能的影响

章节总结

核心知识点回顾

  1. 机器学习核心概念:数据、特征、标签、模型、训练、测试等
  2. 监督学习与无监督学习的区别和应用场景
  3. 完整的模型训练流程:从数据收集到模型部署
  4. 使用TensorFlow.js训练简单分类模型的实战

学习收获

  • 理解了机器学习的基本原理和分类
  • 掌握了模型训练的完整流程
  • 学会了使用TensorFlow.js构建和训练简单的分类模型
  • 能够评估模型性能并进行预测

下一步学习

在下一章中,我们将学习计算机视觉应用,包括图像识别基础、预训练模型使用,以及实战开发图像分类和物体检测应用。


课程分类:前端开发、AI技术开发

学习建议

  • 深入学习线性代数和统计学基础知识
  • 了解更多机器学习算法的原理和应用
  • 实践不同类型的机器学习任务
  • 关注深度学习的最新发展

资源链接

« 上一篇 数据处理与准备 下一篇 » 计算机视觉应用