《PyTorch面试精华》


1 前言
    1.1  PyTorch安装

    1.2  显卡驱动的困惑

    1.3  CUDA安装注意事项

    1.4  cuDNN的介绍

    1.5  Pytorch Lightning介绍

    1.6  PyTorch学习之道

    1.7  PyTorch快速入门

    1.8  PyTorch调参之道

    1.9  PyTorch调参套件

    1.10  手动创建虚拟环境

2 深度学习之数学基础
    2.1  希腊字母解读

    2.2  梯度的物理意义

    2.3  图解梯度下降法

    2.4  图解梯度上升法

    2.5  自然梯度

    2.6  泰勒公式的介绍

    2.7  信息与信息熵

    2.8  重要性采样

    2.10  欧几里得范数

    2.11  特征值和特征向量

    2.12  似然函数的理解

    2.13  矩阵秩的深刻理解

3 PyTorch入门疑难点
4 PyTorch全局设置
    4.1  全局设置当前设备

    4.2  全局设置浮点精度

5 PyTorch GPU分布式训练
    5.1  PyTorch GPU基础操作

    5.2  DataParallel用法详解

    5.3  GPU分布式训练模型

    5.4  CUDA_VISIBLE_DEVICES

    5.5  device详细说明

    5.6  to(device)和.cuda()

    5.7  CUDA设备索引

    5.8  GPU设备索引

6 向量的基础与核心
    6.1  Tensor的组成与存储

    6.2  Tensor的grad属性

    6.4  Tensor的叠加

    6.5  禁用梯度计算

    6.6  向量的保存和加载

    6.7  参数向量

    6.8  叶子节点

    6.9  detach原理

    6.10  requires_grad属性

    6.11  Tensor与Numpy互换

    6.12  张量cat操作

    6.13  零维张量

    6.15  squeeze/unsqu...函数

    6.16  argmax和max的区别

    6.17  torch.as_tensor的应用

7 神经网络基础
    7.2  PyTorch计算图

    7.3  查看网络权重参数

    7.4  保存模型

    7.5  Adam相关面试题

    7.6  Train模式和Eval模式

    7.7  线性网络

    7.8  双线性网络

    7.9  惰性线性层

    7.10  PyTorch中的自动微分

    7.12  Dropout机制

    7.13  半精度训练

    7.14  Xavier初始化

    7.15  注意力机制

    7.16  Dataset数据处理

    7.17  StepLR学习率调度器

    7.18  词嵌入的理解

    7.19  TensorDataset的使用

    7.20  模型的保存与加载

    7.21  ModuleList和Sequential

    7.22  Batch Normalization介绍

8 计算机视觉基础知识
    8.1  通道的深刻理解

    8.2  1x1卷积的作用

    8.3  特征提取和可视化

    8.4  反卷积的推导

    8.5  理解卷积

    8.7  空洞卷积

    8.8  池化层的作用

    8.9  感受野与特征图

    8.10  NMS算法

    8.11  特征图尺寸计算

9 循环神经网络基础
    9.2  RNN的介绍

10 注意力机制
    10.1  位置编码的作用

    10.2  位置编码的种类

    10.4  Embedding本质理解

    10.6  Transformer VS CNN/RNN

    10.7  ELMo介绍

11 PyTorch归一化
    11.2  层归一化技术详解

12 激活函数相关内容
    12.1  激活函数简介

    12.2  万能逼近定理

    12.3  指数函数的学习

    12.4  Sigmoid函数的介绍

    12.5  Tanh函数的介绍

    12.6  Softmax函数的实现

    12.7  ReLU函数的介绍

    12.8  Leaky Relu函数的介绍

    12.9  ReLu与非线性的理解

    12.10  Parametric ReLU函数

    12.11  ELU函数介绍

    12.12  神经元死亡的问题

13 思考题的答案
    13.1  思考题的答案解密

ReLu与非线性的理解

创建时间:2024-09-04 更新时间:2025-02-21 阅读次数:1994 次

1、人们的疑惑

ReLU函数是最常见的激活函数,其数学表达式和函数图像如下所示:

ReLU函数的数学表达式

$$ ReLU(x) = max(0,x) $$

ReLU函数的函数图像

当人们看到ReLU函数的图像时候,总是感到疑惑,它看起来就是线性函数,怎么能实现非线性功能呢?

2、ReLU函数的线性与非线性:

ReLU函数具有两面性,既有线性,又有非线性。

当 x>0 时,ReLU 表现为线性函数 f(x)=x。

当 x≤0 时,输出为 0,引入了非线性。

非线性来源:虽然 ReLU 在正区间是线性的,但其在负区间的截断(输出为 0)引入了非线性。多个 ReLU 单元的叠加可以形成复杂的非线性决策边界。

3、ReLU函数实现非线性的方式

  • 多单元组合。多个 ReLU 单元的组合可以逼近复杂的非线性函数。例如,两个 ReLU 单元可以组合成一个"V"形函数。

  • 多层网络。在深层网络中,ReLU 的叠加能够学习到高度非线性的特征表示。

4、ReLU函数实现非线性的代码演示

4.1、两个ReLU函数形成"V"形函数

我们可以通过组合多个 ReLU 单元来实现一个非线性函数,例如一个"V"形函数。然后使用 matplotlib 绘制其示意图。

import numpy as np
import matplotlib.pyplot as plt

# 定义 ReLU 函数
def relu(x):
    return np.maximum(0, x)

# 定义 V 形函数
def v_shape_function(x):
    # 使用两个 ReLU 单元组合
    return relu(x) + relu(-x)

# 生成输入数据
x = np.linspace(-10, 10, 500)
y = v_shape_function(x)

# 绘制图像
plt.figure(figsize=(8, 6))
plt.plot(x, y, label="V-Shaped Function", color="blue", linewidth=2)
plt.title("Nonlinear Function using ReLU", fontsize=16)
plt.xlabel("x", fontsize=14)
plt.ylabel("y", fontsize=14)
plt.grid(True, linestyle="--", alpha=0.6)
plt.axhline(0, color="black", linewidth=1)
plt.axvline(0, color="black", linewidth=1)
plt.legend()
plt.show()

代码说明:

定义两个 ReLU 单元:一个用于正斜率,另一个用于负斜率。组合这两个 ReLU 单元,形成一个"V"形函数。

运行结果:

4.2、五个ReLU函数形成"M"形函数

import numpy as np
import matplotlib.pyplot as plt

# 定义 ReLU 函数
def relu(x):
    return np.maximum(0, x)

# 定义 M 形函数
def double_m_shape_function(x):
    # 使用五个 ReLU 单元组合
    return (
        relu(x + 10) - 2 * relu(x + 5) + 2 * relu(x) - 2 * relu(x - 5) + relu(x - 10)
    )

# 生成输入数据
x = np.linspace(-15, 15, 500)
y = double_m_shape_function(x)

# 绘制图像
plt.figure(figsize=(8, 6))
plt.plot(x, y, label="M-Shaped Function", color="blue", linewidth=2)
plt.title("Nonlinear Function using Five ReLUs", fontsize=16)
plt.xlabel("x", fontsize=14)
plt.ylabel("y", fontsize=14)
plt.grid(True, linestyle="--", alpha=0.6)
plt.axhline(0, color="black", linewidth=1)
plt.axvline(0, color="black", linewidth=1)
plt.legend()
plt.show()

代码说明:

M 形函数:double_m_shape_function(x) 通过组合五个 ReLU 单元实现:

  • relu(x + 10):向左平移 10 个单位。

  • -2 * relu(x + 5):向左平移 5 个单位并向下拉伸。

  • 2 * relu(x):不平移,向上拉伸。

  • -2 * relu(x - 5):向右平移 5 个单位并向下拉伸。

  • relu(x - 10):向右平移 10 个单位。

运行结果:

4.3、多个ReLU函数形成正弦函数

import numpy as np
import matplotlib.pyplot as plt

# 定义 ReLU 函数
def relu(x):
    return np.maximum(0, x)

# 定义逼近正弦函数的 ReLU 组合
def relu_sine_approximation(x, n_segments=20):

    # 计算每个分段的斜率和截距
    segment_width = 2 * np.pi / n_segments  # 每个分段的宽度
    y_approx = np.zeros_like(x)  # 初始化逼近结果

    for i in range(n_segments):
        # 分段起点和终点
        start = -np.pi + i * segment_width
        end = -np.pi + (i + 1) * segment_width

        # 计算分段斜率
        slope = (np.sin(end) - np.sin(start)) / segment_width

        # 计算分段截距
        intercept = np.sin(start) - slope * start

        # 添加 ReLU 单元
        y_approx += slope * relu(x - start) - slope * relu(x - end)

    return y_approx

# 生成输入数据
x = np.linspace(-2 * np.pi, 2 * np.pi, 1000)
y_true = np.sin(x)  # 真实的正弦函数
y_approx = relu_sine_approximation(x, n_segments=20)  # ReLU 逼近的正弦函数

# 绘制图像
plt.figure(figsize=(10, 6))
plt.plot(x, y_true, label="True Sine Function", color="blue", linewidth=2)
plt.plot(x, y_approx, label="ReLU Approximation", color="red", linestyle="--", linewidth=2)
plt.title("Approximating Sine Function with Multiple ReLUs", fontsize=16)
plt.xlabel("x", fontsize=14)
plt.ylabel("y", fontsize=14)
plt.grid(True, linestyle="--", alpha=0.6)
plt.axhline(0, color="black", linewidth=1)
plt.axvline(0, color="black", linewidth=1)
plt.legend()
plt.show()

代码说明:

  • 分段逼近。将正弦函数的一个周期(−π 到 π)分成 n_segments 个分段。对每个分段计算斜率和截距,并用 ReLU 单元拟合。

  • 叠加 ReLU 单元。每个 ReLU 单元对应一个分段,通过斜率和截距调整其形状。将所有 ReLU 单元的输出叠加,形成对正弦函数的逼近。

运行结果:

蓝色曲线是真实的正弦函数。红色虚线是 ReLU 组合逼近的结果。随着 n_segments 的增加,红色虚线会越来越接近蓝色曲线,逼近效果显著提升。

参数调整

n_segments:控制分段数量(ReLU 单元数量)。增加 n_segments 可以提高逼近精度,但计算量也会增加。例如,n_segments=50 已经可以很好地逼近正弦函数。如果需要更高的精度,可以尝试 n_segments=100 或更多。

本教程共117节,当前为第113节!
本教程最新修订时间为:2026-05-08 11:10:53