【PaddlePaddle】基础理论教程 – 机器学习理论实践

本篇讲解机器学习理论。涵盖线性回归与逻辑回归的理论与实践,重点讲解数据预处理、模型构建与训练、性能评估及可视化,结合PaddlePaddle框架,系统学习深度学习开发流程并积累实战经验

☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

【paddlepaddle】基础理论教程 - 机器学习理论实践 - 创想鸟

前言

上一节我们从机器学习的基础出发,逐步实现了线性回归和分类任务。现在我们将通过加州房价预测的线性回归问题,理解了如何使用简单的线性模型进行数值预测。

接着,我们使用Logistic 回归解决了Moon100数据集的分类问题,并通过优化算法提升了模型的准确性。

逐步让大家熟练学习机器学习的理论和实践

一、利用Paddle实现基于线性回归的加州房价预测

1.1 数据集介绍

我们将使用 加州房价数据集(California Housing Dataset)作为本案例的研究对象。该数据集包含 1990年加州普查区 的房价与其他特征信息,用于研究地区特征与房价之间的关系。数据集共有 20640条样本 和 8个特征,目标变量是该地区的房价中位数。

1.1.1 数据集特征说明

以下是数据集中的特征描述:

特征名称 描述 单位

MedInc区域收入中位数万美元HouseAge区域房屋年龄中位数年AveRooms每户平均房间数无单位AveBedrms每户平均卧室数无单位Population区域人口数量人AveOccup每户平均入住人数人Latitude区域纬度度Longitude区域经度度Target(目标变量)房价中位数(待预测)万美元

1.1.2 目标分析

本案例的目标是通过 线性回归模型 预测区域的房价中位数(Target),并评估模型的性能。同时,尝试通过特征工程和正则化方法改进模型效果。

In [1]

# 导入必要库import paddlefrom sklearn.datasets import fetch_california_housingimport pandas as pd# 加载加州房价数据集housing = fetch_california_housing(as_frame=True)# 转换为DataFramedata = housing.frame# 显示数据集基本信息print("数据集基本信息:")print(data.info())# 显示前几行样本print("数据集示例:")print(data.head())# 查看目标变量分布print("目标变量分布(房价中位数):")print(data['MedHouseVal'].describe())
/opt/conda/envs/python35-paddle120-env/lib/python3.10/site-packages/paddle/utils/cpp_extension/extension_utils.py:686: UserWarning: No ccache found. Please be aware that recompiling all source files may be required. You can download and install ccache from: https://github.com/ccache/ccache/blob/master/doc/INSTALL.md  warnings.warn(warning_message)
数据集基本信息:RangeIndex: 20640 entries, 0 to 20639Data columns (total 9 columns): #   Column       Non-Null Count  Dtype  ---  ------       --------------  -----   0   MedInc       20640 non-null  float64 1   HouseAge     20640 non-null  float64 2   AveRooms     20640 non-null  float64 3   AveBedrms    20640 non-null  float64 4   Population   20640 non-null  float64 5   AveOccup     20640 non-null  float64 6   Latitude     20640 non-null  float64 7   Longitude    20640 non-null  float64 8   MedHouseVal  20640 non-null  float64dtypes: float64(9)memory usage: 1.4 MBNone数据集示例:   MedInc  HouseAge  AveRooms  AveBedrms  Population  AveOccup  Latitude    8.3252      41.0  6.984127   1.023810       322.0  2.555556     37.88   1  8.3014      21.0  6.238137   0.971880      2401.0  2.109842     37.86   2  7.2574      52.0  8.288136   1.073446       496.0  2.802260     37.85   3  5.6431      52.0  5.817352   1.073059       558.0  2.547945     37.85   4  3.8462      52.0  6.281853   1.081081       565.0  2.181467     37.85      Longitude  MedHouseVal  0    -122.23        4.526  1    -122.22        3.585  2    -122.24        3.521  3    -122.25        3.413  4    -122.25        3.422  目标变量分布(房价中位数):count    20640.000000mean         2.068558std          1.153956min          0.14999025%          1.19600050%          1.79700075%          2.647250max          5.000010Name: MedHouseVal, dtype: float64

1.2 数据清洗与可视化分析

在机器学习任务中,数据清洗是模型构建的基础环节,目的是处理缺失值、异常值等可能影响模型性能的问题,同时通过可视化分析数据的分布和特征之间的关系。


1.2.1 数据清洗

(1) 缺失值分析

缺失值可能会导致模型无法正常训练。我们需要检查数据集是否存在缺失值,并采取适当措施进行填补或移除。

In [2]

# 检查缺失值missing_values = data.isnull().sum()print("各列缺失值情况:n", missing_values)# 若存在缺失值,可以选择删除或填充# 删除缺失值样本cleaned_data = data.dropna()# 或者使用均值填充filled_data = data.fillna(data.mean())print("清洗后的数据集基本信息:")print(cleaned_data.info())
各列缺失值情况: MedInc         0HouseAge       0AveRooms       0AveBedrms      0Population     0AveOccup       0Latitude       0Longitude      0MedHouseVal    0dtype: int64清洗后的数据集基本信息:RangeIndex: 20640 entries, 0 to 20639Data columns (total 9 columns): #   Column       Non-Null Count  Dtype  ---  ------       --------------  -----   0   MedInc       20640 non-null  float64 1   HouseAge     20640 non-null  float64 2   AveRooms     20640 non-null  float64 3   AveBedrms    20640 non-null  float64 4   Population   20640 non-null  float64 5   AveOccup     20640 non-null  float64 6   Latitude     20640 non-null  float64 7   Longitude    20640 non-null  float64 8   MedHouseVal  20640 non-null  float64dtypes: float64(9)memory usage: 1.4 MBNone

(2) 异常值处理

异常值是指数据中明显偏离常规范围的值。我们通常通过统计方法或可视化工具(如箱线图)来检测异常值。

IQR方法:利用四分位数间距(IQR)检测异常值。

异常值范围:小于 (Q1−1.5×IQR)(Q1−1.5×IQR) 或大于 (Q3+1.5×IQR)(Q3+1.5×IQR) 的值被视为异常值。

In [3]

# 统计每列的上下四分位数和异常值范围for col in data.columns[:-1]:  # 遍历所有特征列    Q1 = data[col].quantile(0.25)    Q3 = data[col].quantile(0.75)    IQR = Q3 - Q1    lower_bound = Q1 - 1.5 * IQR    upper_bound = Q3 + 1.5 * IQR        # 过滤异常值    outliers = data[(data[col]  upper_bound)]    print(f"{col} 列异常值数量:{len(outliers)}")        # 去除异常值(可选)    data = data[(data[col] >= lower_bound) & (data[col] <= upper_bound)]
MedInc 列异常值数量:681HouseAge 列异常值数量:0AveRooms 列异常值数量:439AveBedrms 列异常值数量:1116Population 列异常值数量:1063AveOccup 列异常值数量:528Latitude 列异常值数量:0Longitude 列异常值数量:0

1.3 数据集特征的箱线图可视化

箱线图是一种直观的统计图表,用于展示数据分布及检测异常值。通过绘制箱线图,我们可以快速发现数据的分布情况和离群点

通过箱线图,我们可以观察: 1. 各特征值的分布范围及中心位置。 2. 是否存在显著的离群点。 3. 不同特征的量级差异。

In [4]

!pip install seaborn
Looking in indexes: https://mirror.baidu.com/pypi/simple/, https://mirrors.aliyun.com/pypi/simple/Collecting seaborn  Downloading https://mirrors.aliyun.com/pypi/packages/83/11/00d3c3dfc25ad54e731d91449895a79e4bf2384dc3ac01809010ba88f6d5/seaborn-0.13.2-py3-none-any.whl (294 kB)     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 294.9/294.9 kB 7.5 MB/s eta 0:00:00a 0:00:01Requirement already satisfied: numpy!=1.24.0,>=1.20 in /opt/conda/envs/python35-paddle120-env/lib/python3.10/site-packages (from seaborn) (1.26.4)Requirement already satisfied: pandas>=1.2 in /opt/conda/envs/python35-paddle120-env/lib/python3.10/site-packages (from seaborn) (2.2.3)Requirement already satisfied: matplotlib!=3.6.1,>=3.4 in /opt/conda/envs/python35-paddle120-env/lib/python3.10/site-packages (from seaborn) (3.9.2)Requirement already satisfied: contourpy>=1.0.1 in /opt/conda/envs/python35-paddle120-env/lib/python3.10/site-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (1.3.0)Requirement already satisfied: cycler>=0.10 in /opt/conda/envs/python35-paddle120-env/lib/python3.10/site-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (0.12.1)Requirement already satisfied: fonttools>=4.22.0 in /opt/conda/envs/python35-paddle120-env/lib/python3.10/site-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (4.54.1)Requirement already satisfied: kiwisolver>=1.3.1 in /opt/conda/envs/python35-paddle120-env/lib/python3.10/site-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (1.4.7)Requirement already satisfied: packaging>=20.0 in /opt/conda/envs/python35-paddle120-env/lib/python3.10/site-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (24.1)Requirement already satisfied: pillow>=8 in /opt/conda/envs/python35-paddle120-env/lib/python3.10/site-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (10.4.0)Requirement already satisfied: pyparsing>=2.3.1 in /opt/conda/envs/python35-paddle120-env/lib/python3.10/site-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (3.2.0)Requirement already satisfied: python-dateutil>=2.7 in /opt/conda/envs/python35-paddle120-env/lib/python3.10/site-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (2.9.0.post0)Requirement already satisfied: pytz>=2020.1 in /opt/conda/envs/python35-paddle120-env/lib/python3.10/site-packages (from pandas>=1.2->seaborn) (2024.2)Requirement already satisfied: tzdata>=2022.7 in /opt/conda/envs/python35-paddle120-env/lib/python3.10/site-packages (from pandas>=1.2->seaborn) (2024.2)Requirement already satisfied: six>=1.5 in /opt/conda/envs/python35-paddle120-env/lib/python3.10/site-packages (from python-dateutil>=2.7->matplotlib!=3.6.1,>=3.4->seaborn) (1.16.0)Installing collected packages: seabornSuccessfully installed seaborn-0.13.2

In [5]

import matplotlib.pyplot as pltimport seaborn as sns# 设置画图风格sns.set(style="whitegrid")# 选择部分特征绘制箱线图selected_features = ['MedInc', 'HouseAge', 'AveRooms', 'AveBedrms', 'Population']# 绘制箱线图plt.figure(figsize=(12, 6))sns.boxplot(data=data[selected_features])plt.title("Boxplot of dataset feature.", fontsize=16)plt.xticks(fontsize=12)plt.ylabel("value", fontsize=12)plt.xlabel("feature", fontsize=12)plt.show()

1.4 数据特征归一化

在机器学习任务中,特征归一化 是特征工程的重要步骤。其目的是将不同量纲的特征值映射到相同的尺度范围,从而提高模型的训练效率和性能,尤其是在梯度下降算法和距离相关的模型(如线性回归、逻辑回归和支持向量机)中。


1.4.1 为什么需要特征归一化?

现实数据中,不同特征的取值范围可能存在巨大差异。例如:

收入中位数(MedInc):范围可能为 [0, 15]。人口数量(Population):范围可能为 [500, 40,000]。经纬度(Latitude 和 Longitude):范围为 [30, 50] 和 [-125, -115]。

这种差异会导致以下问题:

梯度更新不均衡:梯度下降时,不同特征的梯度大小会不一致,可能导致模型难以收敛或收敛速度过慢。模型偏向问题:未归一化的特征可能对模型决策产生不均衡的影响,例如范围较大的特征可能主导模型输出。优化器敏感性:大多数优化算法(如SGD)对特征的尺度变化较为敏感。


1.4.2 常见的特征归一化方法

(1) 最小-最大归一化(Min-Max Scaling)

将特征值线性缩放到指定范围(通常为 [0, 1] 或 [-1, 1])。

公式:

[x′=x−min(x)max(x)−min(x)][x′=max(x)−min(x)x−min(x)]

优点:

保持数据分布形状不变。对特征值范围的约束性强。

适用场景:

特征范围已知,且分布无显著异常值。

(2) 标准化(Standardization)

将特征值转化为标准正态分布(均值为0,标准差为1)。

公式: [x′=x−μσ][x′=σx−μ] 其中,(μ)(μ) 为均值,(σ(σ) 为标准差。

优点:

适合处理有偏分布数据。对异常值较为鲁棒。

适用场景:

特征范围未知,且数据分布可能存在不同量级。

(3) 对数缩放(Log Scaling)

对数变换将特征值压缩到较小范围。

公式: [x′=log⁡(x+1)][x′=log(x+1)]

适用场景:

特征值存在长尾分布,且非负。

(4) 归一化的对比

方法 数据分布影响 是否受异常值影响 适用范围

Min-Max归一化不改变分布易受异常值影响特征范围已知标准化转换为标准分布鲁棒特征范围未知,分布不均对数缩放减少长尾效应易受负值影响存在长尾分布In [10]

# # 使用最大最小归一化import numpy as npfrom sklearn.model_selection import train_test_split# 提取特征与目标变量features = data.iloc[:, :-1].valuestarget = data.iloc[:, -1].values# # 最小-最大归一化实现# def min_max_scaling(features):#     min_vals = np.min(features, axis=0)#     max_vals = np.max(features, axis=0)#     return (features - min_vals) / (max_vals - min_vals)# # # 应用归一化# # normalized_features = min_max_scaling(features)# # 数据集划分# X_train, X_test, y_train, y_test = train_test_split(normalized_features, target, test_size=0.2, random_state=42)

In [11]

# 标准化from sklearn.preprocessing import StandardScaler# 标准化实现scaler = StandardScaler()standardized_features = scaler.fit_transform(features)# 数据集划分X_train, X_test, y_train, y_test = train_test_split(standardized_features, target, test_size=0.2, random_state=42)

In [12]

import paddleimport paddle.nn.functional as F# 将数据转换为Paddle张量X_train_tensor = paddle.to_tensor(X_train, dtype='float32')X_test_tensor = paddle.to_tensor(X_test, dtype='float32')# 使用Paddle实现标准化mean = paddle.mean(X_train_tensor, axis=0)std = paddle.std(X_train_tensor, axis=0)X_train_normalized = (X_train_tensor - mean) / stdX_test_normalized = (X_test_tensor - mean) / stdprint("标准化后的训练数据:", X_train_normalized.numpy()[:5])
标准化后的训练数据: [[-0.5087326   1.4234632   0.12109426  0.05857366 -0.6497711   0.15639436   1.0031793  -1.2958153 ] [ 1.0481998  -0.8750934   0.9622561   2.2335987  -0.49749768  0.10866082   0.655153   -1.1851951 ] [ 0.66350424 -0.8750934  -0.05120656  0.2758133  -0.42929187 -0.79060733   0.7539172  -1.1751386 ] [ 2.9235477   0.76673275  2.0087693  -0.01296391  0.00373571 -0.74548185  -0.72284335  0.6651809 ] [-1.147807    0.5204589  -0.953951    0.690019   -0.93687    -0.79818255  -0.4500659   0.75066024]]
W0108 10:22:09.703733   294 dygraph_functions.cc:83253] got different data type, run type promotion automatically, this may cause data type been changed.

(5)可视化归一化效果

In [13]

import matplotlib.pyplot as pltplt.figure(figsize=(12, 6))plt.boxplot(features, labels=data.columns[:-1])plt.title("Feature distribution before normalization") # 归一化前特征分布plt.xticks(rotation=45)plt.show()
/tmp/ipykernel_294/2547550394.py:4: MatplotlibDeprecationWarning: The 'labels' parameter of boxplot() has been renamed 'tick_labels' since Matplotlib 3.9; support for the old name will be dropped in 3.11.  plt.boxplot(features, labels=data.columns[:-1])

In [15]

plt.figure(figsize=(12, 6))plt.boxplot(standardized_features)plt.title("Feature distribution after normalization") # 归一化后特征分布(Min-Max)plt.show()

1.5 模型构建

在完成数据处理后,我们开始进入模型构建部分。本文将使用 PaddlePaddle 框架来自定义一个线性回归模型,并通过最小二乘法的解析解直接求解模型参数,从而避免复杂的迭代训练过程。


1.5.1 自定义 Linear 算子

PaddlePaddle 提供了灵活的算子设计接口,可以通过继承 paddle.nn.Layer 来定义自定义算子。我们首先构建一个简单的线性算子。

In [16]

import paddleimport paddle.nn as nnimport paddle.nn.functional as F# 自定义Linear算子class Linear(nn.Layer):    def __init__(self, in_features, out_features):        super(Linear, self).__init__()        # 初始化权重和偏置        self.weight = self.create_parameter(            shape=[in_features, out_features],            default_initializer=nn.initializer.XavierUniform())        self.bias = self.create_parameter(            shape=[out_features],            default_initializer=nn.initializer.Constant(0.0))    def forward(self, x):        # 线性变换公式:y = Wx + b        return paddle.matmul(x, self.weight) + self.bias

1.5.2 定义 Runner 类

Runner 类是模型训练的核心封装,我们将其用于配置模型、损失函数、优化器,以及完成模型的训练、评价和预测任务。

In [17]

# Runner类定义class Runner:    def __init__(self, input_dim, regularization_lambda=0.01):        """        初始化线性回归模型以及其他必需的参数        """        self.model = Linear(in_features=input_dim, out_features=1)        self.loss_fn = F.mse_loss  # 均方误差损失        self.optimizer = paddle.optimizer.SGD(parameters=self.model.parameters(), learning_rate=0.01)        self.regularization_lambda = regularization_lambda  # L2正则化项    def prepare_model(self, X_train, y_train):        """        使用正规方程(带L2正则化)来求解模型的权重和偏置        """        # 转换为Paddle张量        X_train_tensor = paddle.to_tensor(X_train, dtype='float32')        y_train_tensor = paddle.to_tensor(y_train, dtype='float32')        # 添加偏置项到 X_train        X_train_with_bias = paddle.concat([X_train_tensor, paddle.ones([X_train_tensor.shape[0], 1], dtype='float32')], axis=1)        # 正规方程解析解:W = (X^T X + λI)^-1 X^T y        X_transpose = paddle.transpose(X_train_with_bias, perm=[1, 0])                # 加上正则化项 (λI)        identity_matrix = paddle.eye(X_train_with_bias.shape[1])        regularization_matrix = self.regularization_lambda * identity_matrix                # 计算正规方程解        weights = paddle.matmul(            paddle.inverse(paddle.matmul(X_transpose, X_train_with_bias) + regularization_matrix),            paddle.matmul(X_transpose, y_train_tensor)        )        # 拆分权重和偏置        self.model.weight.set_value(weights[:-1].reshape([X_train.shape[1], 1]))  # 权重调整为二维张量        self.model.bias.set_value(weights[-1:].reshape([1]))  # 偏置调整为一维张量        print("解析解求得的模型参数:")        print("权重:", self.model.weight.numpy())        print("偏置:", self.model.bias.numpy())    def evaluate_model(self, X_test, y_test):        """        使用测试集进行模型评价        """        X_test_tensor = paddle.to_tensor(X_test, dtype='float32')        y_test_tensor = paddle.to_tensor(y_test, dtype='float32')        # 进行预测        predictions = self.model(X_test_tensor)        loss = self.loss_fn(predictions, y_test_tensor)        print("模型评价 - 测试集均方误差:", loss.numpy())        return predictions.numpy()    def predict(self, X_new):        """        对新数据进行预测        """        X_new_tensor = paddle.to_tensor(X_new, dtype='float32')        predictions = self.model(X_new_tensor)        return predictions.numpy()

1.5.3 使用 Runner 类来构建线性回归模型并完成训练、评价和预测。

In [18]

# 加载数据X_train, X_test, y_train, y_test = X_train_normalized, X_test_normalized, y_train, y_test# 创建 Runner 实例runner = Runner(input_dim=X_train.shape[1])# 使用最小二乘法解析解求解模型参数runner.prepare_model(X_train, y_train)# 评价模型predictions = runner.evaluate_model(X_test, y_test)# 对新数据进行预测X_new = X_test[:5]  # 假设我们使用测试集的前5条数据进行预测predicted_prices = runner.predict(X_new)print("预测结果(前5条):", predicted_prices)
解析解求得的模型参数:权重: [[ 0.7456653 ] [ 0.16260225] [-0.16771364] [ 0.1250522 ] [ 0.04790141] [-0.27607393] [-0.8478774 ] [-0.7796167 ]]偏置: [2.025095]模型评价 - 测试集均方误差: 1.9318573预测结果(前5条): [[1.5605581] [1.4985472] [1.6648219] [1.4926147] [1.280458 ]]

二、线性分类

在前边的学习过程中,通过对线性回归的学习,为我们提供了一种直观且基础的预测模型。通过将输入特征与目标变量之间的关系表示为一个线性方程,线性回归帮助我们理解了如何在多维空间中找到最优的拟合直线。然而,除了回归问题,分类问题也是机器学习中的重要领域。在许多应用场景中,我们需要根据输入数据的特征对样本进行分类。此时,线性分类模型成为了一种非常有效的选择。

与线性回归模型相似,线性分类模型通过线性方程来决定样本所属的类别。然而,线性分类的目标是将数据点分割成不同的类别,而不是预测一个连续的数值。接下来,我们将介绍线性分类的定义及其核心思想,并展示如何使用机器学习方法进行分类。

线性分类是一种基于线性模型的分类方法,旨在通过一个线性决策边界将样本分为不同的类别。其基本思想是利用线性函数来对数据进行分割,从而使得数据能够被映射到不同的类别标签。

具体来说,给定一个输入数据点 (x∈Rn)(x∈Rn),线性分类模型试图通过一个线性方程进行分类:

[y=sign(w1x1+w2x2+⋯+wnxn+b)][y=sign(w1x1+w2x2+⋯+wnxn+b)]

其中:

(w1,w2,…,wn)(w1,w2,…,wn) 是模型的权重,表示每个特征的重要性。(x1,x2,…,xn)(x1,x2,…,xn) 是输入特征。(b)(b) 是偏置项,用于调整决策边界的位置。(y)(y) 是模型的输出,它表示预测的类别,通常取值为 (±1)(±1) 或 0 和 1。

在训练过程中,线性分类器的目标是找到最佳的权重 (w)(w) 和偏置 (b)(b),使得决策边界能够最有效地将不同类别的样本分开。

与回归问题不同,线性分类模型的输出通常是一个类别标签,而不是一个连续的数值。根据训练数据的不同,线性分类器会调整其参数,使得分类边界最大程度地正确地划分样本。

常见的线性分类模型

常见的线性分类模型包括:

感知机(Perceptron):一种最简单的线性分类模型,基于梯度下降方法,通过不断调整权重来找到分割不同类别的超平面。支持向量机(SVM):通过最大化类别之间的间隔来寻找最优超平面,从而提高分类精度。逻辑回归(Logistic Regression):尽管名字中包含“回归”,它是一种广泛使用的线性分类模型,输出的是概率值,经过Sigmoid激活函数后用于二分类问题。Softmax回归: 解决了二分类问题中逻辑回归的局限,能够处理多个类别的分类问题。在Softmax回归中,我们通过一个线性模型计算每个类别的得分,然后通过Softmax函数将这些得分转换为概率,最终输出每个类别的预测概率

2.1 介绍 Logistic 回归

Logistic 回归(Logistic Regression)是一种广泛使用的统计模型,尽管其名称中带有“回归”二字,但它实际上是一种分类模型,主要用于解决二分类问题。Logistic 回归的核心思想是通过一个线性模型预测数据属于某一类别的概率。

2.1 Logistic 回归模型

在二分类问题中,我们通过线性模型计算一个实数值,然后使用Sigmoid函数(也称为Logistic函数)将其转换为一个0到1之间的概率值,表示数据属于某一类别的可能性。

假设输入特征为 (x∈Rn)(x∈Rn),模型的输出为类别 (y∈{0,1})(y∈{0,1}),则 Logistic 回归模型的预测概率为:

[P(y=1∣x)=σ(wTx+b)][P(y=1∣x)=σ(wTx+b)]

其中:

$( w $) 是特征的权重,$( x $) 是输入特征向量,$( b $) 是偏置项,$( sigma $) 是 Sigmoid 函数,它将线性函数的输出转换为概率。

2.2 相关的激活函数

Logistic 回归中使用的核心激活函数是 Sigmoid 函数,它的数学表达式为:

[σ(z)=11+e−z][σ(z)=1+e−z1]

Sigmoid 函数的作用是将输入值 ( z ) 映射到区间 ( (0, 1) ),这使得它非常适合用来表示概率。对于输入值 ( z ) 较大时,Sigmoid 输出接近 1,而当输入值较小时,输出接近 0。

Sigmoid 函数的特性

当 (z→+∞)(z→+∞),(σ(z)→1)(σ(z)→1)。当 (z→−∞)(z→−∞),(σ(z)→0)(σ(z)→0)。Sigmoid 函数是一个S型曲线,具有平滑的导数,适合用于梯度下降优化。

2.3. Logistic 函数实现代码

使用PaddlePaddle框架,实现一个简单的 Logistic 回归模型的实现代码

Logistic 函数实现了标准的 Sigmoid 激活函数 (σ(z)=11+e−z)(σ(z)=1+e−z1)

使用 paddle.linspace 生成从 -10 到 10 的等间距数值,并将这些值输入到 Logistic 函数中,计算其对应的输出值。

In [19]

import paddle# 定义 Logistic 函数def Logistic(x):    return 1 / (1 + paddle.exp(-x))# 创建一组从 -10 到 10 的数值x = paddle.linspace(-10, 10, 10000)# 计算 Logistic 函数值y = Logistic(x)# 打印结果的前几项print(y[:10])  # 输出前10项# 可视化 Logistic 函数import matplotlib.pyplot as pltplt.plot(x.tolist(), y.tolist(),color = 'red')plt.title('Sigmoid Function (Logistic)')plt.xlabel('z')plt.ylabel('σ(z)')plt.grid(True)plt.show()
Tensor(shape=[10], dtype=float32, place=Place(cpu), stop_gradient=True,       [0.00004540, 0.00004549, 0.00004558, 0.00004567, 0.00004576, 0.00004585,        0.00004595, 0.00004604, 0.00004613, 0.00004622])

函数解析

X轴:表示线性模型的输出 (z=wTx+b)(z=wTx+b)Y轴:表示通过 Sigmoid 激活函数得到的概率值 (σ(z))(σ(z))。当 ( z ) 较大时,Sigmoid 输出接近 1,表示类别1的概率很高。当 ( z ) 较小时,Sigmoid 输出接近 0,表示类别0的概率很高。在 ( z = 0 ) 时,Sigmoid 输出为 0.5,表示类别1和类别0的概率相等。

2.4 基于Logistic实现Moon1000数据集回归测试

我们将构建一个简单的二分类数据集,使用的是 Moon1000 数据集,这是一个由两个半月形状的数据集,常用于测试二分类模型的性能。

make_moons:我们生成了 1000 条带有噪声(noise=0.1)的二分类数据,形成了两个半月形状的数据集。

StandardScaler:对数据进行标准化处理,使其均值为 0,标准差为 1,这有助于提高模型训练的效果。

plt.scatter:通过不同的颜色和标记(Class 0 用蓝色,Class 1 用红色)绘制两类数据点。

In [20]

# 使用 `sklearn.datasets.make_moons` 来生成一个二分类的数据集。随机抽取其中的 1000 个样本,import numpy as npimport matplotlib.pyplot as pltfrom sklearn.datasets import make_moonsfrom sklearn.preprocessing import StandardScaler# 生成 Moon 数据集X, y = make_moons(n_samples=1000, noise=0.1, random_state=42)# 数据标准化scaler = StandardScaler()X_scaled = scaler.fit_transform(X)# 可视化数据分布plt.figure(figsize=(8, 6))plt.scatter(X_scaled[y == 0][:, 0], X_scaled[y == 0][:, 1], color='b', label='Class 0', s=10)plt.scatter(X_scaled[y == 1][:, 0], X_scaled[y == 1][:, 1], color='r', label='Class 1', s=10)plt.title('Moon1000 Dataset Visualization')plt.xlabel('Feature 1')plt.ylabel('Feature 2')plt.legend()plt.grid(True)plt.show()

In [21]

# 拆分数据集(训练集、验证集、测试集)from sklearn.model_selection import train_test_split# 第一次拆分:将数据集分为训练集(60%)和临时集(40%)X_train, X_temp, y_train, y_temp = train_test_split(X_scaled, y, test_size=0.4, random_state=42)# 第二次拆分:将临时集分为验证集(20%)和测试集(20%)X_val, X_test, y_val, y_test = train_test_split(X_temp, y_temp, test_size=0.5, random_state=42)# 打印数据集形状print(f"训练集特征 X_train 形状: {X_train.shape}")print(f"验证集特征 X_val 形状: {X_val.shape}")print(f"测试集特征 X_test 形状: {X_test.shape}")print(f"训练集标签 y_train 形状: {y_train.shape}")print(f"验证集标签 y_val 形状: {y_val.shape}")print(f"测试集标签 y_test 形状: {y_test.shape}")
训练集特征 X_train 形状: (600, 2)验证集特征 X_val 形状: (200, 2)测试集特征 X_test 形状: (200, 2)训练集标签 y_train 形状: (600,)验证集标签 y_val 形状: (200,)测试集标签 y_test 形状: (200,)

2.5 构建 Logistic 回归模型

In [22]

import paddleimport paddle.nn as nnimport paddle.optimizer as optimimport paddle.nn.functional as F# 自定义 Logistic 回归模型(仅用 paddle.matmul)class LogisticRegression(nn.Layer):    def __init__(self, input_dim):        super(LogisticRegression, self).__init__()        # 定义线性层        self.params = {}        self.params['w'] = paddle.zeros([input_dim, 1])        self.params['b'] = paddle.zeros(shape = [1])        self.fc = nn.Linear(input_dim, 1)    def forward(self, x):        # 使用 paddle.matmul 计算加权和        logits = paddle.matmul(x, self.params['w']) + self.params['b']        outputs = Logistic(logits)        return outputs  # 这里没有使用激活函数 sigmoid

In [23]

paddle.seed(0)input = paddle.randn([3, 4])print(input)model = LogisticRegression(4)output = model(input)print(output)
Tensor(shape=[3, 4], dtype=float32, place=Place(cpu), stop_gradient=True,       [[-0.75711036, -0.38059190,  0.10946669,  1.34467661],        [-0.84002435, -1.27341712,  2.47224617,  0.14070207],        [ 0.60608417,  0.23396523,  1.35604191,  0.10350471]])Tensor(shape=[3, 1], dtype=float32, place=Place(cpu), stop_gradient=True,       [[0.50000000],        [0.50000000],        [0.50000000]])

2.6 损失函数介绍

损失函数(Loss Function),也叫代价函数(Cost Function),在机器学习中是评估模型预测结果与真实结果之间差异的一个函数。损失函数的主要作用是通过量化模型的预测误差来引导优化过程,最终帮助模型调整参数,使得预测结果更加精确。

1. 损失函数的定义与作用

损失函数是一个数学函数,用来衡量模型的预测输出与真实标签之间的差异。其核心作用是:

量化预测误差用于优化算法的目标函数引导模型参数的调整

通常,损失函数的值越小,表示模型的预测结果与真实值的差距越小,因此,优化算法的目标就是通过不断最小化损失函数来训练模型。

2. 损失函数的公式

在不同的任务中,损失函数有所不同。常见的损失函数包括:

均方误差(Mean Squared Error,MSE):用于回归问题,公式如下:

L(y,y^)=1N∑i=1N(yi−y^i)2L(y,y^)=N1i=1∑N(yi−y^i)2

其中,yiyi 为真实值,y^iy^i 为预测值,NN 为样本数量。

交叉熵(Cross-Entropy):用于分类问题,特别是二分类和多分类任务,公式如下:

对于二分类,交叉熵损失函数可以写为:

L(y,y^)=−1N∑i=1N[yilog⁡(y^i)+(1−yi)log⁡(1−y^i)]L(y,y^)=−N1i=1∑N[yilog(y^i)+(1−yi)log(1−y^i)]

对于多分类,交叉熵损失函数可以写为:

L(y,y^)=−∑i=1Cyilog⁡(y^i)L(y,y^)=−i=1∑Cyilog(y^i)

其中,yiyi 是实际类别标签(通常是一个 one-hot 向量),y^iy^i 是预测的类别概率,CC 是类别数。

3. 交叉熵损失函数

交叉熵损失函数主要用于分类问题,尤其是在处理二分类和多分类任务时广泛应用。交叉熵的基本思想是量化两个概率分布之间的差异,通常用于衡量模型输出的概率分布与实际分布之间的差距。

二分类交叉熵:当标签是二分类时,交叉熵损失函数用于度量二进制分类模型输出的概率和真实标签之间的差异。

多分类交叉熵:对于多分类问题,交叉熵损失会计算所有类别的概率差异,并选择具有最大概率的类别作为模型的输出。

4. 构建交叉熵损失函数类代码

以下是一个简单的交叉熵损失函数实现,代码使用了 PaddlePaddle 框架:

In [24]

import paddleimport paddle.nn as nnclass CrossEntropyLoss(nn.Layer):    def __init__(self):        super(CrossEntropyLoss, self).__init__()    def forward(self, logits, labels):        """        计算交叉熵损失        :param logits: 预测值(通常是模型的输出,没有经过 softmax 的原始值)        :param labels: 真实标签,通常是 one-hot 编码        :return: 交叉熵损失        """        # 使用 PaddlePaddle 的函数计算交叉熵损失        loss = nn.functional.cross_entropy(logits, labels)        return loss# 示例:使用自定义交叉熵损失函数logits = paddle.to_tensor([[1.2, 0.3, -0.5], [0.7, 1.4, -1.0]], dtype='float32')  # 模拟模型输出labels = paddle.to_tensor([0, 1], dtype='int64')  # 假设有两个样本,标签分别为类别 0 和类别 1loss_fn = CrossEntropyLoss()loss = loss_fn(logits, labels)print("交叉熵损失:", loss.numpy())
交叉熵损失: 0.46265036

2.7 回归模型优化 – 梯度优化

梯度优化(Gradient Optimization)是机器学习中最常用的优化方法之一,它基于梯度下降算法(Gradient Descent)来通过调整模型的参数,最小化损失函数,从而提高模型的预测性能。在训练过程中,模型的参数通过计算梯度并朝着损失函数的最小值方向进行更新。

1. 梯度计算

梯度计算是优化算法的核心步骤,它用于计算损失函数相对于模型参数的偏导数。梯度描述了损失函数在某个点上的变化率,并指示了如何调整参数以减少损失。

损失函数:在逻辑回归中,常用的损失函数是交叉熵损失函数,计算的是模型预测与实际标签之间的差异。偏导数:偏导数是衡量一个参数对损失函数变化的敏感程度,即参数变化时,损失函数的变化量。计算每个参数的偏导数可以告诉我们如何调整该参数以减少损失。

2. 偏导数计算

对于逻辑回归的交叉熵损失函数,损失函数可以表示为:

L(y,y^)=−(ylog⁡(y^)+(1−y)log⁡(1−y^))L(y,y^)=−(ylog(y^)+(1−y)log(1−y^))

其中,y^=σ(Wx+b)y^=σ(Wx+b) 为模型的预测输出,yy 为实际标签,WW 为权重,bb 为偏置,σσ 为Sigmoid激活函数。

为了优化权重和偏置,我们需要计算损失函数相对于模型参数(权重 WW 和偏置 bb)的偏导数。通过链式法则,我们可以得到每个参数的梯度:

对权重 WW 的梯度:

∂L∂W=1N∑i=1N(y^i−yi)xi∂W∂L=N1i=1∑N(y^i−yi)xi

对偏置 bb 的梯度:

∂L∂b=1N∑i=1N(y^i−yi)∂b∂L=N1i=1∑N(y^i−yi)

3. Backward函数的实现

为了在逻辑回归模型中实现梯度计算,我们需要增加一个 backward 函数来计算损失函数的梯度。该函数将根据模型的输入数据和实际标签计算出每个参数的梯度,并将其存储在模型的 grads 属性中。

In [25]

import paddleimport paddle.nn as nn# 自定义 Logistic 回归模型(仅用 paddle.matmul)class LogisticRegression(nn.Layer):    def __init__(self, input_dim):        super(LogisticRegression, self).__init__()        # 定义线性层        self.params = {}        self.params['w'] = paddle.zeros([input_dim, 1])  # 初始化权重        self.params['b'] = paddle.zeros(shape=[1])  # 初始化偏置        self.fc = nn.Linear(input_dim, 1)    def forward(self, x):        # 使用 paddle.matmul 计算加权和        logits = paddle.matmul(x, self.params['w']) + self.params['b']        outputs = self.sigmoid(logits)        return outputs    def sigmoid(self, x):        # Sigmoid 激活函数        return 1 / (1 + paddle.exp(-x))    def backward(self, x, y):        """        计算损失函数对模型参数的梯度,并将其存放在 grads 属性中。        :param x: 输入特征        :param y: 真实标签        :return: None        """        # 计算预测输出        logits = paddle.matmul(x, self.params['w']) + self.params['b']        y_pred = self.sigmoid(logits)        # 计算损失函数对权重的偏导数        dw = paddle.matmul(paddle.transpose(x, [1, 0]), (y_pred - y)) / x.shape[0]        db = paddle.sum(y_pred - y) / x.shape[0]        # 将梯度存放在 grads 属性中        self.grads = {}        self.grads['w'] = dw        self.grads['b'] = db        # 输出计算的梯度        print("梯度 w:", dw.numpy())        print("梯度 b:", db.numpy())

In [26]

# 使用 backward 函数进行梯度计算# 模型创建与输入数据生成input_dim = 2model = LogisticRegression(input_dim)# 随机生成输入数据和标签x_sample = paddle.to_tensor([[0.5, 1.0], [1.5, -1.0], [1.0, 2.0]], dtype='float32')y_sample = paddle.to_tensor([[1], [0], [1]], dtype='float32')# 前向计算outputs = model(x_sample)print("模型输出:", outputs.numpy())# 计算梯度model.backward(x_sample, y_sample)# 查看存储的梯度print("存储在 grads 中的权重梯度:", model.grads['w'].numpy())print("存储在 grads 中的偏置梯度:", model.grads['b'].numpy())
模型输出: [[0.5] [0.5] [0.5]]梯度 w: [[ 0.       ] [-0.6666667]]梯度 b: -0.16666667存储在 grads 中的权重梯度: [[ 0.       ] [-0.6666667]]存储在 grads 中的偏置梯度: -0.16666667

2.8 模型优化 – 设计优化器

在模型训练过程中,优化器的作用是根据计算得到的梯度来调整模型的参数,逐步最小化损失函数,从而提高模型的预测能力。常见的优化算法有梯度下降(Gradient Descent)及其变种,如随机梯度下降(SGD)、Adam等。

1. 梯度下降法(Gradient Descent)

梯度下降法是最基本的优化算法,主要思想是通过计算损失函数的梯度,并按梯度的反方向更新参数,以便使损失函数逐步减小,直至收敛。

梯度下降的更新公式

对于一个模型的参数 θθ,在每一次迭代中,梯度下降法通过以下公式更新参数:

θ:=θ−η∂L∂θθ:=θ−η∂θ∂L

其中:

θθ 是模型的参数(例如,权重 WW 和偏置 bb)。ηη 是学习率(learning rate),控制着每次更新的步长。∂L∂θ∂θ∂L 是损失函数 LL 关于参数 θθ 的梯度。

计算梯度并进行更新

假设我们有一个模型 f(x,θ)f(x,θ),其损失函数为 L(y,f(x,θ))L(y,f(x,θ)),我们首先通过反向传播计算出模型的梯度。然后使用梯度下降算法,通过以下步骤更新参数:

计算损失函数 LL 对于模型参数 θθ 的梯度 ∂L∂θ∂θ∂L。

根据梯度更新模型参数:

θnew=θ−η⋅∂L∂θθnew=θ−η⋅∂θ∂L

在每次迭代中,参数会沿着梯度的反方向进行调整。

2. 优化器设计 – 自定义梯度下降

在设计优化器时,我们需要使用梯度下降法来更新模型参数。假设我们有一个简单的逻辑回归模型,已经通过 backward 函数计算了梯度,接下来,我们使用优化器来更新模型的权重和偏置。

In [27]

import paddleimport paddle.nn as nn# 自定义 Logistic 回归模型(仅用 paddle.matmul)class LogisticRegression(nn.Layer):    def __init__(self, input_dim):        super(LogisticRegression, self).__init__()        # 定义线性层        self.params = {}        self.params['w'] = paddle.zeros([input_dim, 1])  # 初始化权重        self.params['b'] = paddle.zeros(shape=[1])  # 初始化偏置        self.fc = nn.Linear(input_dim, 1)    def forward(self, x):        # 使用 paddle.matmul 计算加权和        logits = paddle.matmul(x, self.params['w']) + self.params['b']        outputs = self.sigmoid(logits)        return outputs    def sigmoid(self, x):        # Sigmoid 激活函数        return 1 / (1 + paddle.exp(-x))    def backward(self, x, y):        """        计算损失函数对模型参数的梯度,并将其存放在 grads 属性中。        :param x: 输入特征        :param y: 真实标签        :return: None        """        # 计算预测输出        logits = paddle.matmul(x, self.params['w']) + self.params['b']        y_pred = self.sigmoid(logits)        # 计算损失函数对权重的偏导数        dw = paddle.matmul(paddle.transpose(x, [1, 0]), (y_pred - y)) / x.shape[0]        db = paddle.sum(y_pred - y) / x.shape[0]        # 将梯度存放在 grads 属性中        self.grads = {}        self.grads['w'] = dw        self.grads['b'] = db        # 输出计算的梯度        # print("梯度 w:", dw.numpy())        # print("梯度 b:", db.numpy())    def update_params(self, lr=0.01):        """        使用梯度下降法更新模型的权重和偏置        :param lr: 学习率        :return: None        """        # 更新权重和偏置        self.params['w'] = self.params['w'] - lr * self.grads['w']        self.params['b'] = self.params['b'] - lr * self.grads['b']        # print("更新后的权重 w:", self.params['w'].numpy())        # print("更新后的偏置 b:", self.params['b'].numpy())

2.9 模型训练与优化

通过以下步骤进行模型训练,并应用自定义优化器来更新参数:

1.定义模型并初始化。

2.计算每个小批次的梯度。

3.使用梯度下降法更新模型参数。

4.重复以上步骤,直到损失函数收敛。

In [71]

# 将数据集转换为 Paddle 张量X_train_tensor = paddle.to_tensor(X_train, dtype='float32')y_train_tensor = paddle.to_tensor(y_train.reshape(-1, 1), dtype='float32')  # 确保标签形状匹配# 构建模型input_dim = X_train.shape[1]  # 输入特征的维度model = LogisticRegression(input_dim)# 训练过程epochs = 10000learning_rate = 0.01for epoch in range(epochs):    # 前向计算    outputs = model(X_train_tensor)        # 计算梯度    model.backward(X_train_tensor, y_train_tensor)        # 更新参数    model.update_params(lr=learning_rate)        # 每200回合打印一次损失值    if (epoch + 1) % 200 == 0:        # 计算预测值与实际标签的损失        logits = paddle.matmul(X_train_tensor, model.params['w']) + model.params['b']        predictions = model.sigmoid(logits)        loss = paddle.mean(-y_train_tensor * paddle.log(predictions) - (1 - y_train_tensor) * paddle.log(1 - predictions))        print(f"Epoch {epoch + 1}/{epochs}, Loss: {loss.numpy()}")
Epoch 200/10000, Loss: 0.434282124042511Epoch 400/10000, Loss: 0.35399749875068665Epoch 600/10000, Loss: 0.31881678104400635Epoch 800/10000, Loss: 0.2997851073741913Epoch 1000/10000, Loss: 0.2880668342113495Epoch 1200/10000, Loss: 0.2802077829837799Epoch 1400/10000, Loss: 0.2746124267578125Epoch 1600/10000, Loss: 0.2704521119594574Epoch 1800/10000, Loss: 0.26725637912750244Epoch 2000/10000, Loss: 0.2647395730018616Epoch 2200/10000, Loss: 0.26271817088127136Epoch 2400/10000, Loss: 0.2610691785812378Epoch 2600/10000, Loss: 0.25970688462257385Epoch 2800/10000, Loss: 0.25856953859329224Epoch 3000/10000, Loss: 0.25761178135871887Epoch 3200/10000, Loss: 0.25679925084114075Epoch 3400/10000, Loss: 0.25610560178756714Epoch 3600/10000, Loss: 0.2555100917816162Epoch 3800/10000, Loss: 0.25499647855758667Epoch 4000/10000, Loss: 0.25455155968666077Epoch 4200/10000, Loss: 0.2541647255420685Epoch 4400/10000, Loss: 0.2538272738456726Epoch 4600/10000, Loss: 0.25353190302848816Epoch 4800/10000, Loss: 0.2532727122306824Epoch 5000/10000, Loss: 0.2530447244644165Epoch 5200/10000, Loss: 0.25284361839294434Epoch 5400/10000, Loss: 0.2526659667491913Epoch 5600/10000, Loss: 0.25250861048698425Epoch 5800/10000, Loss: 0.2523690164089203Epoch 6000/10000, Loss: 0.2522450387477875Epoch 6200/10000, Loss: 0.25213468074798584Epoch 6400/10000, Loss: 0.25203630328178406Epoch 6600/10000, Loss: 0.2519485056400299Epoch 6800/10000, Loss: 0.2518700659275055Epoch 7000/10000, Loss: 0.25179991126060486Epoch 7200/10000, Loss: 0.25173699855804443Epoch 7400/10000, Loss: 0.2516807019710541Epoch 7600/10000, Loss: 0.25163009762763977Epoch 7800/10000, Loss: 0.25158464908599854Epoch 8000/10000, Loss: 0.2515437602996826Epoch 8200/10000, Loss: 0.2515070140361786Epoch 8400/10000, Loss: 0.25147390365600586Epoch 8600/10000, Loss: 0.25144410133361816Epoch 8800/10000, Loss: 0.2514171898365021Epoch 9000/10000, Loss: 0.2513929307460785Epoch 9200/10000, Loss: 0.25137099623680115Epoch 9400/10000, Loss: 0.2513512074947357Epoch 9600/10000, Loss: 0.2513332962989807Epoch 9800/10000, Loss: 0.2513171434402466Epoch 10000/10000, Loss: 0.25130248069763184

3.0 模型评估与预测

在训练完模型之后,我们需要对模型进行评估并在新的数据上进行预测。在这一部分,我们将介绍如何使用训练好的 Logistic 回归模型来进行评估和预测。

1. 模型评估

模型评估的核心是通过计算损失函数(如交叉熵损失)来度量模型在测试集上的表现。我们可以使用测试集的真实标签和模型预测结果计算损失,以了解模型在训练后是否有较好的泛化能力。

评估公式:

L(y,y^)=−1N∑i=1N[yilog⁡(y^i)+(1−yi)log⁡(1−y^i)]L(y,y^)=−N1i=1∑N[yilog(y^i)+(1−yi)log(1−y^i)]

其中,yy 为真实标签,y^y^ 为预测输出,NN 为样本数。

In [72]

# 模型评估def evaluate_model(model, X_test, y_test):    # 前向计算    logits = paddle.matmul(X_test, model.params['w']) + model.params['b']    predictions = model.sigmoid(logits)        # 计算交叉熵损失    loss = paddle.mean(-y_test * paddle.log(predictions) - (1 - y_test) * paddle.log(1 - predictions))    print(f"测试集损失: {loss.numpy()}")        # 预测标签    predicted_labels = (predictions > 0.5).astype('float32')  # 将 predicted_labels 转为 float32        # 计算准确率    accuracy = paddle.mean(paddle.cast(predicted_labels == y_test, dtype='float32'))        print(f"测试集准确率: {accuracy.numpy()}")    return predicted_labels.numpy()# 将数据转换为 Paddle 张量X_test_tensor = paddle.to_tensor(X_test, dtype='float32')y_test_tensor = paddle.to_tensor(y_test, dtype='float32')predicted_labels = evaluate_model(model, X_test_tensor, y_test_tensor)# print("预测标签:", predicted_labels)
测试集损失: 1.567063570022583测试集准确率: 0.5015000104904175

In [ ]


In [73]

# 将数据转换为 Paddle 张量X_test_tensor = paddle.to_tensor(X_test, dtype='float32')y_test_tensor = paddle.to_tensor(y_test, dtype='float32')# 测试阶段的预测predictions = model(X_test_tensor)  # 概率值predicted_labels = (predictions > 0.5).astype('int32')  # 转为二分类标签# # 检查预测结果分布# print("预测概率分布:", predictions.numpy().flatten())# print("预测标签分布:", predicted_labels.numpy().flatten())# 可视化对比plt.figure(figsize=(10, 6))# 实际标签可视化plt.subplot(1, 2, 1)plt.scatter(X_test[:, 0], X_test[:, 1], c=y_test.flatten(), cmap='bwr', alpha=0.6)plt.title('Actual Labels')plt.xlabel('Feature 1')plt.ylabel('Feature 2')# 预测标签可视化plt.subplot(1, 2, 2)plt.scatter(X_test[:, 0], X_test[:, 1], c=predicted_labels.numpy().flatten(), cmap='bwr', alpha=0.6)plt.title('Predicted Labels')plt.xlabel('Feature 1')plt.ylabel('Feature 2')plt.tight_layout()plt.show()

以上就是【PaddlePaddle】基础理论教程 – 机器学习理论实践的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/72274.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月13日 15:08:08
下一篇 2025年11月13日 15:44:45

相关推荐

  • 什么是资金费率?为什么玩合约有时候需要付费给别人?

    binance币安交易所 注册入口: APP下载: 欧易OKX交易所 注册入口: APP下载: 火币交易所: 注册入口: APP下载: 资金费率是永续合约中的核心机制,它的存在是为了确保合约市场的价格能紧密跟随标的资产的现货价格。这笔费用并非由交易所收取,而是在多空双方的交易者之间直接结算,它就像一…

    2025年12月9日
    000
  • 什么是“HODL”和“钻石手”?币圈人为什么总说要“拿住”?

    binance币安交易所 注册入口: APP下载: 欧易OKX交易所 注册入口: APP下载: 火币交易所: 注册入口: APP下载: 在加密货币世界里,“HODL”和“钻石手”是投资者们常挂在嘴边的词。它们代表着一种坚定的持币信念,即无论市场如何剧烈波动,都选择长期持有资产,相信其未来价值。 “H…

    2025年12月9日
    000
  • 什么是“创世区块”?它对比特币有什么特殊的意义?

    binance币安交易所 注册入口: APP下载: 欧易OKX交易所 注册入口: APP下载: 火币交易所: 注册入口: APP下载: 创世区块,又称区块0,是比特币区块链中第一个被创建的区块。它由中本聪在2009年1月3日创建,是整个比特币系统的基石,所有后续区块都直接或间接地链接到它,犹如一部史…

    2025年12月9日
    000
  • 中心化交易所(CEX)与去中心化交易所(DEX)对比

    在数字资产交易的广阔天地中,中心化交易所(cex)和去中心化交易所(dex)是两种主流的平台类型,它们各自拥有独特的优势和局限性。理解两者的核心差异,对于投资者来说至关重要,因为它直接影响到交易的安全性、便捷性以及所能提供的资产种类。本文将深入探讨cex和dex的运作机制、特点以及它们在实际应用中的…

    好文分享 2025年12月9日
    000
  • 如何选择加密货币交易所?关键考量因素

    在数字资产浪潮汹涌的今天,选择一个可靠、安全且功能强大的加密货币交易所,是每位投资者迈向成功的第一步。面对市面上琳琅满目的选择,如何拨开迷雾,精准识别出最适合自己的交易平台,成为了一个至关重要的问题。本文将深入探讨选择加密货币交易所时应重点关注的几个关键考量因素,帮助您构建一套完善的筛选标准,确保您…

    好文分享 2025年12月9日
    000
  • 美联储举办支付创新会议,聚焦稳定币与代币化,讨论传统金融与DeFi融合

    美联储举办支付创新会议,聚焦稳定币与代币化 近日,美国联邦储备系统举办了一场备受瞩目的支付创新会议,其核心议题直指稳定币与资产代币化这两大金融科技前沿领域。此次会议汇集了来自传统金融机构、科技公司、监管机构以及新兴区块链项目的专家与决策者,共同探讨支付系统的未来演变,特别是传统金融与去中心化金融如何…

    2025年12月9日
    000
  • Meme币官方网址是什么_Meme币官方网站入口

    Meme币,又称模因币,是一种起源于互联网文化、笑话或热点事件的加密货币。它们通常不具备复杂的底层技术或宏大的应用场景,其价值更多地依赖于社区的共识和持续的热度推动。 一、知名Meme币官方入口 1、由于Meme币是一个宽泛的类别,并非单一项目,因此没有统一的“官方网站”。每个Meme币项目都有其独…

    2025年12月9日
    000
  • 2025币安(币an)最新官方地址 币安官方认证首页地址入口

    币安最新官网访问入口: 币安官方APP下载地址: 访问币安时,务必通过币安官方认证入口进入,以确保页面安全与账户隐私。进入官网后,可在首页显眼位置看到“注册”与“登录”按钮。建议将该页面加入浏览器收藏夹,方便日后直接访问,避免误入仿冒网站。 币安官方注册流程 币安支持邮箱与手机号两种注册方式,操作简…

    2025年12月9日
    000
  • 什么是K线图?我如何看懂红绿柱子来判断买卖时机?

    binance币安交易所 注册入口: APP下载: 欧易OKX交易所 注册入口: APP下载: 火币交易所: 注册入口: APP下载: K线图,又称蜡烛图,是金融市场中记录特定周期内价格走势的图表。它直观地展示了开盘价、最高价、最低价和收盘价,是技术分析中判断多空力量和预测未来行情的核心工具。 认识…

    2025年12月9日
    000
  • 什么是Gas费?为什么转账有时那么贵,如何节省?

    binance币安交易所 注册入口: APP下载: 欧易OKX交易所 注册入口: APP下载: 火币交易所: 注册入口: APP下载: Gas费是区块链网络上的交易手续费,就像汽车的燃油。它用于支付给验证者处理和验证交易的报酬,是确保网络安全与稳定运行的核心机制。 为什么转账有时那么贵? 1、网络拥…

    2025年12月9日
    000
  • 币安交易所官网入口 币安交易平台APP最新版v3.6.0安装指南

    币安(binance)是全球知名的数字货币交易所,提供现货、合约、理财、质押等多元化服务。本文将介绍币安交易所官网入口的安全访问方式,并为你讲解币安交易平台app最新版v3.6.0的安装指南,帮助新用户轻松完成下载安装与账户注册。 币安官网访问入口 建议通过币安官方认证网址进入官网,避免因非官方链接…

    2025年12月9日 好文分享
    000
  • Meme币官网平台入口_Meme币官网主页在线平台链接

    meme币,又称模因币,是一类源于互联网文化、表情包或网络热点的加密货币。它们通常具有高度的社区驱动性和病毒式传播特性,从最初的玩笑和实验,逐渐演变为数字资产领域中一个充满活力与投机色彩的独特分支。这类代币的价值往往与社区的关注度、社交媒体的热度以及市场情绪紧密相连,吸引了大量寻求高风险高回报机会的…

    2025年12月9日
    000
  • 美联储将于10月21日举办加密支付创新会议

    美联储将于10月21日举办一场主题为加密支付创新的重要会议,这一消息迅速在全球金融科技领域引起广泛关注。此次会议被视为传统金融监管机构与新兴加密世界之间一次关键的对话,标志着全球最大的中央银行之一正以更加开放和审慎的态度,深入探索数字货币与支付系统的未来。 会议背景与战略意图 随着区块链技术的成熟和…

    2025年12月9日
    000
  • 以太坊合约如何实现权限控制_以太坊合约权限管理方法

    在以太坊智能合约中,权限控制是保障资产安全和系统稳定运行的关键。一个设计良好的权限管理机制可以有效防止未经授权的操作,确保只有特定角色的地址才能执行敏感功能。本文将介绍几种主流的以太坊合约权限管理方法,帮助开发者构建更安全的去中心化应用。 一、所有权模式(Ownable) 1、所有权模式是最基础、最…

    2025年12月9日
    000
  • 黄金疯涨,比特币却原地发呆?“数字黄金”人设崩了?

    黄金疯涨,比特币却原地发呆? 当国际金价一路高歌猛进,接连突破历史高位时,加密货币世界的“数字黄金”——比特币,却显得异常平静,甚至有些步履蹒跚。这种强烈的反差,不禁让许多投资者和市场观察者心生疑虑:比特币那顶被寄予厚望的“数字黄金”桂冠,是否已经摇摇欲坠?它作为价值储存和避险资产的人设,难道真的崩…

    2025年12月9日
    000
  • 比特币地址怎么生成_比特币地址生成的具体方法

    binance币安交易所 注册入口: APP下载: 欧易OKX交易所 注册入口: APP下载: 火币交易所: 注册入口: APP下载: 获取一个比特币地址是参与数字资产交易的第一步,它就像您的银行账号一样,用于接收和发送比特币。本文将为您介绍几种主流且安全的比特币地址生成方法,帮助您轻松上手。 一、…

    2025年12月9日
    000
  • 美联储10月降息概率达99%,加密市场迎来政策关键周

    美联储降息预期达99%叠加SEC批准加密ETP新规,美元走弱与监管明确化推动资产重配,黄金、美股成长板块及加密货币迎来利好,机构加速布局数字资产,市场进入流动性宽松与制度创新共振的新阶段。 2025年10月的第三周,全球金融市场正屏息凝视,等待一个几乎确定无疑的货币事件——美联储的再次降息。根据CM…

    2025年12月9日
    000
  • 如何查看比特币交易记录_查询比特币交易记录的步骤

    binance币安交易所 注册入口: APP下载: 欧易OKX交易所 注册入口: APP下载: 火币交易所: 注册入口: APP下载: 查询比特币的交易记录是了解资金流向和确认交易状态的关键一步。由于其网络的公开透明特性,任何人都可以通过使用区块链浏览器轻松追踪任何一笔交易的详细信息。 一、准备查询…

    2025年12月9日
    000
  • 瑞波币最新价格查询_瑞波币官方网站入口

    瑞波(ripple)是一个旨在连接全球银行、支付提供商和数字资产交易所的开放支付网络,其原生数字货币被称为瑞波币(xrp)。与许多主流加密货币不同,xrp专注于为金融机构提供一种高效、低成本的跨境支付解决方案,凭借其极快的交易确认速度和高度的可扩展性,在全球支付领域展现了巨大的潜力,成为了数字货币市…

    2025年12月9日
    000
  • 瑞波币价格预测官网_瑞波币官方网站首页链接

    对于关注瑞波(XRP)的用户来说,获取官方信息和可靠的市场数据至关重要。本文旨在为您提供瑞波官方网站的直接入口,并介绍几个权威的数据分析平台,帮助您全面了解项目动态和市场行情。 一、瑞波(Ripple)官方网站入口 1、官方网站是了解瑞波技术和生态系统发展的最核心渠道。在这里,您可以获取关于公司、技…

    2025年12月9日
    000

发表回复

登录后才能评论
关注微信