Python Numpy 实现神经网络自动训练:反向传播与激活函数的应用详解

Python Numpy 实现神经网络自动训练:反向传播与激活函数的应用详解

这篇文章介绍了如何使用 Python 的 Numpy 库来实现神经网络的自动训练,重点展示了反向传播算法和激活函数的应用。反向传播是神经网络训练的核心,能够通过计算梯度来优化模型参数,使得预测更加精准。文中详细演示了如何使用 Numpy 进行神经网络的前向预测、反向传播更新、误差计算,并通过引入 ReLU 等激活函数提升模型的非线性拟合能力。最后,通过对比训练前后的结果,展示了加入激活函数后模型性能的显著提升,适合初学者和爱好者学习神经网络的基础原理与应用。

文章目录

  • Python Numpy 实现神经网络自动训练:反向传播与激活函数的应用详解
      • 一 简单介绍反向传播
      • 二 用 Numpy 来做神经网络
        • 没有训练
        • 开始训练
      • 三 加入激活函数
        • 常用激活函数
        • 非线性计算,不加激活函数
        • 非线性计算,加入激活函数
      • 四 完整代码示例
      • 五 源码地址

一 简单介绍反向传播

反向传播(Backpropagation)是训练神经网络的核心算法,用于通过计算损失函数相对于网络各个参数的梯度,逐步优化这些参数,从而使模型的预测结果更加准确。使用梯度反向更新规则做神经网络参数优化调整。
这段代码计算每一层神经层的更新幅度,让神经网络对数据拟合变好,不理解先当工具方法记住。

def backprop(dz, layer, layer_in, learning_rate=0.01):
    """
    进行反向传播,更新当前层的权重和偏置,并计算传递给前一层的梯度。

    参数:
    dz: 当前层输出的梯度(损失函数对激活输出的偏导数)
    layer: 当前层的参数字典,包含权重 "w" 和偏置 "b"
    layer_in: 输入到当前层的激活值
    learning_rate: 学习率,用于控制参数更新的步长,默认值为 0.01

    返回:
    new_dz: 传递给前一层的梯度
    """

    # 计算损失函数对权重的梯度,layer_in.T 是当前层输入的转置,dot(dz) 进行矩阵乘法
    gw = layer_in.T.dot(dz)
    
    # 计算损失函数对偏置的梯度,按列求和,保留维度,求得每个偏置的梯度
    gb = np.sum(dz, axis=0, keepdims=True)
    
    # 计算传递给前一层的梯度,使用当前层的权重转置与 dz 相乘
    new_dz = dz.dot(layer["w"].T)
    
    # 更新当前层的权重:使用学习率乘以权重梯度,然后加到原有的权重上(梯度上升)
    layer["w"] += learning_rate * gw
    
    # 更新当前层的偏置:同样使用学习率乘以偏置梯度,然后加到原有的偏置上
    layer["b"] += learning_rate * gb
    
    # 返回传递给前一层的梯度,以便继续进行反向传播
    return new_dz

二 用 Numpy 来做神经网络

没有训练
def predict(x, l1, l2):
    o1 = x.dot(l1["w"]) + l1["b"]
    o2 = o1.dot(l2["w"]) + l2["b"]
    return [o1, o2]


def predict01():
    # 数据
    x = np.linspace(-1, 1, 10)[:, None]  # shape [10, 1]
    y = np.random.normal(loc=0, scale=0.2, size=[10, 1]) + x  # shape [10, 1]

    # 搭建模型
    l1 = layer(1, 3)
    l2 = layer(3, 1)

    draw_line(x, predict(x, l1, l2)[-1])
    draw_scatter(x, y)

运行结果

在这里插入图片描述

可以看出在没有训练的时候,模型预测的结果与实际 y 值在数量级上存在较大差异。

开始训练
def predict02():
    # 数据
    x = np.linspace(-1, 1, 10)[:, None]  # shape [10, 1]
    y = np.random.normal(loc=0, scale=0.2, size=[10, 1]) + x  # shape [10, 1]
    l1 = layer(1, 3)
    l2 = layer(3, 1)

    # 训练 50 次
    learning_rate = 0.01
    for i in range(50):
        # 前向预测
        o1, o2 = predict(x, l1, l2)

        # 误差计算
        if i % 10 == 0:
            average_cost = np.mean(np.square(o2 - y))
            print(average_cost)

        # 反向传播,梯度更新
        dz2 = -2 * (o2 - y)  # 输出误差 (o2 - y)**2 的导数
        dz1 = backprop(dz2, l2, o1)
        _ = backprop(dz1, l1, x)

    # 画一个训练后的图,对比上文中有数值问题的线
    draw_line(x, predict(x, l1, l2)[-1])
    draw_scatter(x, y)

运行结果

在这里插入图片描述

三 加入激活函数

常用激活函数
# 激活函数
def relu(x):
    return np.maximum(0, x)


def relu_derivative(x):  # 导数
    return np.where(x > 0, np.ones_like(x), np.zeros_like(x))


def tanh(x):
    return np.tanh(x)


def tanh_derivative(x):  # 导数
    return 1 - np.square(np.tanh(x))


def sigmoid(x):
    return 1 / (1 + np.exp(-x))


def sigmoid_derivative(x):  # 导数
    o = sigmoid(x)
    return o * (1 - o)

非线性计算,不加激活函数
def predict03():
    # 非线性计算
    x = np.linspace(-1, 1, 30)[:, None]  # shape [30, 1]
    y = np.random.normal(loc=0, scale=0.2, size=[30, 1]) + x ** 2  # shape [30, 1]

    # draw_scatter(x, y)
    # 搭建模型
    l1 = layer(1, 10)
    l2 = layer(10, 1)

    # 训练 300 次
    learning_rate = 0.01
    for i in range(300):
        # 前向预测
        o1, o2 = predict(x, l1, l2)

        # 误差计算
        if i % 10 == 0:
            average_cost = np.mean(np.square(o2 - y))
            print(average_cost)

        # 反向传播,梯度更新
        dz2 = -2 * (o2 - y)  # 输出误差 (o2 - y)**2 的导数
        dz1 = backprop(dz2, l2, o1)
        _ = backprop(dz1, l1, x)

    draw_line(x, predict(x, l1, l2)[-1])
    draw_scatter(x, y)

运行结果

在这里插入图片描述

模型训练结果在量级上出现较大差距,欠拟合。

非线性计算,加入激活函数
def predict04():
    # 非线性计算
    x = np.linspace(-1, 1, 30)[:, None]  # shape [30, 1]
    y = np.random.normal(loc=0, scale=0.2, size=[30, 1]) + x ** 2  # shape [30, 1]
    # 搭建模型
    l1 = layer(1, 10)
    l2 = layer(10, 1)
    # 训练 300 次
    learning_rate = 0.01
    for i in range(300):
        # 前向预测
        o1, a1, o2 = predictjihuo(x, l1, l2)

        # 误差计算
        if i % 10 == 0:
            average_cost = np.mean(np.square(o2 - y))
            print(average_cost)

        # 反向传播,梯度更新
        dz2 = -2 * (o2 - y)  # 输出误差 (o2 - y)**2 的导数
        dz1 = backprop(dz2, l2, a1)
        dz1 *= relu_derivative(o1)  # 这里要添加对应激活函数的反向传播
        _ = backprop(dz1, l1, x)

    draw_line(x, predictjihuo(x, l1, l2)[-1])
    draw_scatter(x, y)

运行结果

在这里插入图片描述

模型成功拟合了这些异常数据点,说明非线性激活函数确实非常有效。

四 完整代码示例

# This is a sample Python script.
from matplotlib import pyplot as plt
import numpy as np


# Press ⌃R to execute it or replace it with your code.
# Press Double ⇧ to search everywhere for classes, files, tool windows, actions, and settings.
def draw_scatter(x, y):
    # 使用 matplotlib 的 scatter 方法来绘制散点图
    # x.ravel() 和 y.ravel() 将 x 和 y 的二维数组转换为一维数组,适合作为散点图的输入
    plt.scatter(x.ravel(), y.ravel())
    # 显示图表
    plt.show()


def draw_line(x, y):
    idx = np.argsort(x.ravel())
    plt.plot(x.ravel()[idx], y.ravel()[idx])
    # plt.show()


def layer(in_dim, out_dim):
    weights = np.random.normal(loc=0, scale=0.1, size=[in_dim, out_dim])
    bias = np.full([1, out_dim], 0.1)
    return {"w": weights, "b": bias}


# 激活函数
def relu(x):
    return np.maximum(0, x)


def relu_derivative(x):  # 导数
    return np.where(x > 0, np.ones_like(x), np.zeros_like(x))


def tanh(x):
    return np.tanh(x)


def tanh_derivative(x):  # 导数
    return 1 - np.square(np.tanh(x))


def sigmoid(x):
    return 1 / (1 + np.exp(-x))


def sigmoid_derivative(x):  # 导数
    o = sigmoid(x)
    return o * (1 - o)


def backprop(dz, layer, layer_in, learning_rate=0.01):
    """
    进行反向传播,更新当前层的权重和偏置,并计算传递给前一层的梯度。

    参数:
    dz: 当前层输出的梯度(损失函数对激活输出的偏导数)
    layer: 当前层的参数字典,包含权重 "w" 和偏置 "b"
    layer_in: 输入到当前层的激活值
    learning_rate: 学习率,用于控制参数更新的步长,默认值为 0.01

    返回:
    new_dz: 传递给前一层的梯度
    """

    # 计算损失函数对权重的梯度,layer_in.T 是当前层输入的转置,dot(dz) 进行矩阵乘法
    gw = layer_in.T.dot(dz)

    # 计算损失函数对偏置的梯度,按列求和,保留维度,求得每个偏置的梯度
    gb = np.sum(dz, axis=0, keepdims=True)

    # 计算传递给前一层的梯度,使用当前层的权重转置与 dz 相乘
    new_dz = dz.dot(layer["w"].T)

    # 更新当前层的权重:使用学习率乘以权重梯度,然后加到原有的权重上(梯度上升)
    layer["w"] += learning_rate * gw

    # 更新当前层的偏置:同样使用学习率乘以偏置梯度,然后加到原有的偏置上
    layer["b"] += learning_rate * gb

    # 返回传递给前一层的梯度,以便继续进行反向传播
    return new_dz


def predictjihuo(x, l1, l2):
    o1 = x.dot(l1["w"]) + l1["b"]
    a1 = relu(o1)  # 这里我添加了一个激活函数
    o2 = a1.dot(l2["w"]) + l2["b"]
    return [o1, a1, o2]


def predict(x, l1, l2):
    """
    预测函数,执行前向传播,计算两层神经网络的输出。

    参数:
    x: 输入数据,形状为 [N, 输入特征数],此处为 [10, 1]。
    l1: 第一层的参数字典,包含权重 "w" 和偏置 "b"。
    l2: 第二层的参数字典,包含权重 "w" 和偏置 "b"。

    返回:
    o1: 第一层的输出结果。
    o2: 第二层的输出结果(最终输出)。
    """
    # 第一层的输出,x.dot(l1["w"]) 是线性组合,+ l1["b"] 加上偏置
    o1 = x.dot(l1["w"]) + l1["b"]

    # 第二层的输出,o1.dot(l2["w"]) 是线性组合,+ l2["b"] 加上偏置
    o2 = o1.dot(l2["w"]) + l2["b"]

    # 返回两层的输出,o1 为第一层的输出,o2 为最终的输出
    return [o1, o2]


def predict01():
    """
    模拟预测和数据绘制函数,包含数据生成、模型搭建、前向预测和绘图。
    """
    # 生成输入数据 x,使用 np.linspace 生成从 -1 到 1 的 10 个均匀分布的点,并reshape为 [10, 1]
    x = np.linspace(-1, 1, 10)[:, None]  # 形状 [10, 1]

    # 生成目标值 y,基于 x 加上高斯噪声,模拟真实数据,形状为 [10, 1]
    y = np.random.normal(loc=0, scale=0.2, size=[10, 1]) + x  # 形状 [10, 1]

    # 搭建神经网络模型
    # 第一层:输入维度为 1,输出维度为 3(即3个神经元)
    l1 = layer(1, 3)

    # 第二层:输入维度为 3,输出维度为 1
    l2 = layer(3, 1)

    # 使用 predict 函数进行前向传播,绘制预测结果
    # 只提取第二层的输出 o2 来绘制预测的线
    draw_line(x, predict(x, l1, l2)[-1])

    # 绘制真实数据点的散点图
    draw_scatter(x, y)


def predict02():
    # 数据
    x = np.linspace(-1, 1, 10)[:, None]  # shape [10, 1]
    y = np.random.normal(loc=0, scale=0.2, size=[10, 1]) + x  # shape [10, 1]
    l1 = layer(1, 3)
    l2 = layer(3, 1)

    # 训练 50 次
    learning_rate = 0.01
    for i in range(50):
        # 前向预测
        o1, o2 = predict(x, l1, l2)

        # 误差计算
        if i % 10 == 0:
            average_cost = np.mean(np.square(o2 - y))
            print(average_cost)

        # 反向传播,梯度更新
        dz2 = -2 * (o2 - y)  # 输出误差 (o2 - y)**2 的导数
        dz1 = backprop(dz2, l2, o1)
        _ = backprop(dz1, l1, x)

    # 画一个训练后的图,对比上文中有数值问题的线
    draw_line(x, predict(x, l1, l2)[-1])
    draw_scatter(x, y)


def predict03():
    # 非线性计算
    x = np.linspace(-1, 1, 30)[:, None]  # shape [30, 1]
    y = np.random.normal(loc=0, scale=0.2, size=[30, 1]) + x ** 2  # shape [30, 1]

    # draw_scatter(x, y)
    # 搭建模型
    l1 = layer(1, 10)
    l2 = layer(10, 1)

    # 训练 300 次
    learning_rate = 0.01
    for i in range(300):
        # 前向预测
        o1, o2 = predict(x, l1, l2)

        # 误差计算
        if i % 10 == 0:
            average_cost = np.mean(np.square(o2 - y))
            print(average_cost)

        # 反向传播,梯度更新
        dz2 = -2 * (o2 - y)  # 输出误差 (o2 - y)**2 的导数
        dz1 = backprop(dz2, l2, o1)
        _ = backprop(dz1, l1, x)

    draw_line(x, predict(x, l1, l2)[-1])
    draw_scatter(x, y)


def predict04():
    # 非线性计算
    x = np.linspace(-1, 1, 30)[:, None]  # shape [30, 1]
    y = np.random.normal(loc=0, scale=0.2, size=[30, 1]) + x ** 2  # shape [30, 1]
    # 搭建模型
    l1 = layer(1, 10)
    l2 = layer(10, 1)
    # 训练 300 次
    learning_rate = 0.01
    for i in range(300):
        # 前向预测
        o1, a1, o2 = predictjihuo(x, l1, l2)

        # 误差计算
        if i % 10 == 0:
            average_cost = np.mean(np.square(o2 - y))
            print(average_cost)

        # 反向传播,梯度更新
        dz2 = -2 * (o2 - y)  # 输出误差 (o2 - y)**2 的导数
        dz1 = backprop(dz2, l2, a1)
        dz1 *= relu_derivative(o1)  # 这里要添加对应激活函数的反向传播
        _ = backprop(dz1, l1, x)

    draw_line(x, predictjihuo(x, l1, l2)[-1])
    draw_scatter(x, y)


def print_hi(name):
    # Use a breakpoint in the code line below to debug your script.
    print(f'Hi, {name}')  # Press ⌘F8 to toggle the breakpoint.
    # 模型前向预测
    # 数据
    x = np.linspace(-1, 1, 10)[:, None]  # shape [10, 1]
    y = np.random.normal(loc=0, scale=0.2, size=[10, 1]) + x  # shape [10, 1]
    # draw_scatter(x, y)
    # 模型
    l1 = layer(1, 3)
    l2 = layer(3, 1)

    # 计算
    o = x.dot(l1["w"]) + l1["b"]
    print("第一层出来后的 shape:", o.shape)

    o = o.dot(l2["w"]) + l2["b"]
    print("第二层出来后的 shape:", o.shape)

    print("output:", o)
    # draw_scatter(x, o)
    # 简单介绍反向传播
    # predict01()
    # predict02()
    # 加入激活函数
    # 非线性计算,没有激活函数的网络训练,量级上的差距大
    # predict03()
    # 非线性计算,加入激活函数
    predict04()


# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    print_hi('神经网络-自动训练')

# See PyCharm help at https://www.jetbrains.com/help/pycharm/

复制粘贴并覆盖到你的 main.py 中运行,运行结果如下。

Hi, 神经网络-自动训练
第一层出来后的 shape: (10, 3)
第二层出来后的 shape: (10, 1)
output: [[0.08015376]
 [0.08221984]
 [0.08428592]
 [0.086352  ]
 [0.08841808]
 [0.09048416]
 [0.09255024]
 [0.09461632]
 [0.0966824 ]
 [0.09874848]]
0.2226335913018929
0.18084056623965614
0.17646520657891238
0.16955062165383475
0.15974897747454914
0.14609449775016456
0.12879398035319886
0.11000871768876343
0.09272999949822598
0.07986100731357502
0.07149628207512877
0.06657668787644673
0.06412748050655417
0.06308965708664192
0.06255298788129363
0.06233764319523034
0.06229224784095634
0.062220235356859256
0.06227320308423159
0.06227607241875045
0.06218961938206315
0.062183519685144004
0.06220136162617964
0.062260925337883535
0.06228186644083771
0.062212564435570314
0.06214763225225857
0.062190709318072676
0.06225667345334308
0.06227302776778138

五 源码地址

代码地址:

国内看 Gitee 之 numpy/神经网络-自动训练.py

国外看 GitHub 之 numpy/神经网络-自动训练.py

引用 莫烦 Python

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/896963.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

文献阅读:通过深度神经网络联合建模多个切片构建3D整体生物体空间图谱

文献介绍 文献题目: 通过深度神经网络联合建模多个切片构建3D整体生物体空间图谱 研究团队: 杨灿(香港科技大学)、吴若昊(香港科技大学) 发表时间: 2023-10-19 发表期刊: Nature M…

01 漫画解说-图片框的分割

to 查找最佳的轮廓模式 import cv2 as cv import numpy as np from matplotlib import pyplot as pltimg cv.imread(data/test02.png,0) ret,thresh1 cv.threshold(img,127,255,cv.THRESH_BINARY) ret,thresh2 cv.threshold(img,127,255,cv.THRESH_BINARY_INV) ret,thres…

搭建代购系统时如何保证商品信息的真实性和可靠性

搭建代购系统时,可从以下几个方面保证商品信息的真实性和可靠性: 一、供应商管理: 严格筛选供应商:对供应商进行全面的背景调查,包括其经营资质、信誉记录、行业口碑等。只选择与正规、有良好信誉的供应商合作&#…

LINUX1.2

1.一切都是一个文件 (硬盘) 2.系统小型 轻量型,300个包 3.避免令人困惑的用户界面 ------------------> 就是没有复杂的图形界面 4.不在乎后缀名,有没有都无所谓,不是通过后缀名来定义文件的类型(win…

JSON 注入攻击 API

文章目录 JSON 注入攻击 API"注入所有东西"是"聪明的"发生了什么? 什么是 JSON 注入?为什么解析器是问题所在解析不一致 JSON 解析器互操作性中的安全问题处理重复密钥的方式不一致按键碰撞响应不一致JSON 序列化(反序列化)中的不一致 好的。JSON 解析器…

免费开源AI助手,颠覆你的数字生活体验

Apt Full作为一款开源且完全免费的软件,除了强大的自然语言处理能力,Apt Full还能够对图像和视频进行一系列复杂的AI增强处理,只需简单几步即可实现专业级的效果。 在图像处理方面,Apt Full提供了一套全面的AI工具,包…

springboot 同时上传文件和JSON对象

控制器代码 PostMapping("/upload") public ResponseEntity<String> handleFileUpload(RequestPart("file") MultipartFile file,RequestPart("user") User user) {// 处理文件和用户信息return ResponseEntity.ok("File and user i…

【MATLAB实例】批量提取.csv数据并根据变量名筛选

【MATLAB实例】批量提取.csv数据并根据变量名筛选 准备&#xff1a;数据说明MATLAB批量提取参考 准备&#xff1a;数据说明 .csv数据如下&#xff1a; 打开某表格数据&#xff0c;如下&#xff1a;&#xff08;需要说明的是此数据含表头&#xff09; 需求说明&#xff1a;需…

升级Unity后产生的Objects内存泄露现象

1&#xff09;升级Unity后产生的Objects内存泄露现象 2&#xff09;能否使用OnDemandRendering API来显示帧率 3&#xff09;Unity闪退问题 4&#xff09;配置表堆内存如何优化 这是第405篇UWA技术知识分享的推送&#xff0c;精选了UWA社区的热门话题&#xff0c;涵盖了UWA问答…

中航资本:大幅加仓!社保基金重仓股曝光

跟着上市公司三季报布满宣告&#xff0c;社保基金2024年三季度末重仓股及持股改变状况浮出水面。 Wind数据闪现&#xff0c;到10月21日&#xff0c;已有191家上市公司宣告了2024年三季报&#xff0c;其间有34家上市公司的前十大流通股东中呈现了社保基金的身影&#xff0c;社保…

从零开始学PHP之变量作用域数据类型

一、数据类型 上篇文章提到了数据类型&#xff0c;在PHP中支持以下几种类型 String &#xff08;字符串&#xff09;Integer&#xff08;整型&#xff09;Float &#xff08;浮点型&#xff09;Boolean&#xff08;布尔型&#xff09;Array&#xff08;数组&#xff09;Objec…

天锐绿盾 vs Ping32:企业级加密软件大比拼

在信息安全日益重要的今天&#xff0c;企业级加密软件成为了企业保护敏感数据的得力助手。在众多加密软件中&#xff0c;天锐绿盾与Ping32凭借各自的优势&#xff0c;赢得了市场的广泛认可。那么&#xff0c;这两款软件究竟有何异同&#xff1f;哪款更适合您的企业呢&#xff1…

Java 输入与输出(I/O)流的装饰流【处理流】

Java I/O流的装饰流 按照Java 输入与输出&#xff08;I/O)流的处理功能&#xff1a;I/O流可分为低级的节点流和高级的装饰流&#xff08;又称处理流&#xff09;。 节点流是直接从数据源&#xff08;数据源可以是文件、数组、内存或网络&#xff09;读/写数据的输入输出流&am…

西南交通大学计算机软件专业上岸难度分析

C哥专业提供——计软考研院校选择分析专业课备考指南规划 西南交通大学计算机科学与技术2024届考研难度整体呈现"稳中有升"的态势。学硕实际录取33人&#xff0c;复试分数线362分&#xff0c;复试录取率71.74%&#xff1b;专硕&#xff08;计算机技术&#xff09;实际…

Mac M3安装VMWare Fusion

最近学习Spark需要下载VM Ware&#xff0c;但是我的电脑是MAC M3系列&#xff0c;百度说不能下载Workstation Pro&#xff0c;Workstation Pro 适用于Windows、Linux系统。而MAC M系列电脑需要下载Fusion Pro 。 Fusion Pro的下载页面很难找到。根据以下指引可正确下载&#x…

OpenCV物体跟踪:使用CSRT算法实现实时跟踪

目录 简介 CSRT算法简介 实现步骤 1. 初始化摄像头和跟踪器 2. 读取视频帧和初始化跟踪 3. 实时跟踪和显示结果 4. 显示和退出 5、结果展示 总结 简介 在计算机视觉和视频处理领域&#xff0c;物体跟踪是一项核心技术&#xff0c;它在监控、人机交互、运动分析等方面…

纯前端实现语音合成并输出提示

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>语音合成</title><style>body {max-…

解决mac ssh端终端只有黑白颜色的问题

主要是因为没有开启颜色配置。修改下文件即可 cd ~ vi .zshrc 内容如下 export LS_OPTIONS--colorauto export CLICOLORYes export LSCOLORSExgxcxdxcxegedabagGxGx 关闭终端后重登录&#xff0c;这下有颜色了好看了 配色&#xff1a;目录蓝 可执行绿 软链青 颜色配置 详…

使用网络爬虫爬取豆瓣电影网站的数据

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

MySQL数据库操作——(4)

目录 8 视图 8.1 常见的数据库对象 8.2 视图概述 8.2.1 为什么使用视图&#xff1f; 8.2.2 视图的理解 8.3 创建视图 8.3.1 创建单表视图 8.3.2 创建多表联合视图 8.3.3 基于视图创建视图 8.4 查看视图 8.5 更新视图的数据 8.5.1 一般情况 8.6 修改、删除视图 8.…