《PyTorch 深度学习实践》第10讲 卷积神经网络(基础篇)

news2025/3/13 8:30:07

文章目录

  • 1 卷积层
    • 1.1 torch.nn.Conv2d相关参数
    • 1.2 填充:padding
    • 1.3 步长:stride
  • 2 最大池化层
  • 3 手写数字识别

该专栏内容为对该视频的学习记录:【《PyTorch深度学习实践》完结合集】
专栏的全部代码、数据集和课件全放在个人GitHub了,欢迎自取

1 卷积层

CNN卷积神经网络中的卷积层是其中最为关键的层之一。卷积层利用滤波器(也称为卷积核)在输入数据上进行卷积操作,通过提取局部特征来识别图像中的模式。

卷积层的输入通常是一个多通道(channel)的二维图像,每个通道表示图像的一种特征。卷积核是一个小的二维矩阵,可以看作是卷积层所学习的一种滤波器,它在输入数据上进行滑动窗口操作,将每个窗口与卷积核进行点积运算,得到一个新的特征图。

卷积层通常有多个滤波器,每个滤波器可以学习不同的特征,因此卷积层的输出是多个特征图的叠加,每个特征图对应一个滤波器。这些特征图可以通过非线性激活函数(如ReLU)进行激活,以增强模型的表达能力。

卷积层还有一些重要的参数,例如步长stride、填充padding等,这些参数可以控制卷积核的移动步长和边缘填充方式,以适应不同的输入数据和模型需求。

在深度学习中,卷积层是图像识别、目标检测、语音识别等任务中非常重要的组件之一,因为它可以有效地提取输入数据中的局部特征,从而实现对输入数据的有效表示和分类。

下图是一个简单的卷积操作:

image-20230415232814135

1.1 torch.nn.Conv2d相关参数

卷积层的形状与输入输出之间有密切的关系。卷积层的形状通常由以下几个参数决定:

  1. 输入数据的形状:输入数据的形状通常是一个多通道的二维图像,其维度通常表示为(通道数n,高度,宽度)或(高度,宽度,通道数)。
  2. 卷积核的形状:卷积核的形状通常是一个小的二维矩阵,其维度通常表示为(输出通道数m,输入通道数n,卷积核高度,卷积核宽度)。
  3. 填充方式:填充方式可以控制输入数据在卷积操作之前是否需要在边缘进行填充,以保持输出特征图的大小不变。常见的填充方式包括"VALID"和"SAME",分别表示不进行填充和进行全零填充。
  4. 步长:步长可以控制卷积核在输入数据上的滑动步长,以控制输出特征图的大小和形状。

根据上述参数,卷积层的输出形状可以通过以下公式计算:

  • (输入高度−卷积核高度+2∗填充高度)/步长+1

  • (输入宽度−卷积核宽度+2∗填充宽度)/步长+1

  • 输出通道数m=卷积核数量m

因此,我们可以通过调整卷积核的形状、填充方式、步长等参数,来控制卷积层的输出形状和大小,以适应不同的输入数据和模型需求。

以下图为例,输入数据为n×w×h,卷积层中有m个卷积核,要进行卷积计算,卷积核中的通道数必须与输入数据的通道数n相等,一个卷积核会对应输出数据的一个通道,这里有m个卷积核,所以输出数据的通道数为m。

image-20230415233318409

一般把卷积层表示为四维张量,即:输出数据通道数m(卷积核个数)× 输入数据通道数n(每个卷积核的通道数)× 卷积核宽度 × 卷积核高度

image-20230415235216484

下面这段代码使用PyTorch库构建了一个简单的卷积神经网络模型,包括一个卷积层和一个输入数据。以下是代码的具体解释:

  1. import torch:导入PyTorch库。
  2. in_channels, out_channels, kernel_size = 5, 10, 3:定义输入通道数、输出通道数和卷积核大小,分别赋值为5、10和3。
  3. width, height = 100, 100:定义输入数据的宽度和高度,分别赋值为100。
  4. batch_size = 1:定义批量大小为1。
  5. input = torch.randn(batch_size, in_channels, width, height):生成一个大小为1×5×100×100的输入数据,其中每个元素是从均值为0,方差为1的正态分布中随机采样得到的。
  6. conv = torch.nn.Conv2d(in_channels, out_channels, kernel_size):定义一个卷积层,其中输入通道数为5,输出通道数为10,卷积核大小为3×3。
  7. output = conv(input):对输入数据进行卷积运算,输出结果的大小为1×10×98×98。
  8. print(input.shape):打印输入数据的大小,即1×5×100×100。
  9. print(output.shape):打印卷积层输出的大小,即1×10×98×98。
  10. print(conv.weight.shape):打印卷积层的权重参数大小,其中10个卷积核的形状为5×3×3,即每个卷积核都有5个通道,大小为3×3。
import torch

in_channels, out_channels, kernel_size = 5, 10, 3
width, height = 100, 100
batch_size = 1

input = torch.randn(batch_size, in_channels, width, height)  #输入数据,1*5*100*100,随机数,均值为0,方差为1,正态分布
conv = torch.nn.Conv2d(in_channels, out_channels, kernel_size)  #卷积层,输入通道数5,输出通道数10,卷积核大小3*3
output = conv(input)  #进行卷积运算
print(input.shape)
print(output.shape)
print(conv.weight.shape)  #10个卷积核,每个卷积核的形状为5*3*3
torch.Size([1, 5, 100, 100])
torch.Size([1, 10, 98, 98])
torch.Size([10, 5, 3, 3])

1.2 填充:padding

以下图为例,为了使输出数据的形状和输入数据一样也为 5 × 5 ,而我们的卷积核形状为 3 × 3 的,这时可以在输入数据中外围填充一圈0,即可达到目的。一般地,为了使输出数据形状不变,可以用卷积核的形状除以2,取整,设置为padding参数值。例如这里3除以2,取整为1,padding就设置为1。

image-20230415235757831

通过设置参数padding=1(即在输入数据外填充1圈0),使输出的结果为1 * 1 * 5 * 5,与输入的形状一致:

import torch

input = [3, 4, 6, 5, 7,
         2, 4, 6, 8, 2,
         1, 6, 7, 8, 4,
         9, 7, 4, 6, 2,
         3, 7, 5, 4, 1]
input = torch.tensor(input, dtype=torch.float).view(1, 1, 5, 5)
conv_layer = torch.nn.Conv2d(1, 1, kernel_size=3, padding=1, bias=False)  #padding=1,卷积核大小3*3,输入通道数1,输出通道数1
kernel = torch.tensor([1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=torch.float).view(1, 1, 3, 3)
conv_layer.weight.data = kernel.data  #卷积核的值

output = conv_layer(input)
print(output)
tensor([[[[ 91., 168., 224., 215., 127.],
          [114., 211., 295., 262., 149.],
          [192., 259., 282., 214., 122.],
          [194., 251., 253., 169.,  86.],
          [ 96., 112., 110.,  68.,  31.]]]], grad_fn=<ConvolutionBackward0>)

1.3 步长:stride

卷积层的步长(stride)是指卷积核在进行卷积操作时每次移动的步长大小。具体来说,步长决定了卷积核在水平和垂直方向上每次移动的像素数。

如果步长为1,则卷积核每次只向右移动一个像素,这也是最常见的步长设置。如果步长大于1,则卷积核每次向右移动的像素数会相应增加,这会导致输出特征图的尺寸变小,因为每个卷积核的感受野(receptive field)覆盖的像素数减少。

步长的选择需要根据具体的应用场景和网络结构进行调整。如果希望输出特征图的尺寸更小,可以选择较大的步长;如果希望输出特征图的尺寸与输入特征图相同,则可以选择步长为1。

image-20230416000946527

import torch

input = [3, 4, 6, 5, 7,
         2, 4, 6, 8, 2,
         1, 6, 7, 8, 4,
         9, 7, 4, 6, 2,
         3, 7, 5, 4, 1]
input = torch.tensor(input, dtype=torch.float).view(1, 1, 5, 5)
conv_layer = torch.nn.Conv2d(1, 1, kernel_size=3, stride=2, bias=False)  #stride=2,卷积核大小3*3,输入通道数1,输出通道数1
kernel = torch.tensor([1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=torch.float).view(1, 1, 3, 3)
conv_layer.weight.data = kernel.data  #卷积核的值

output = conv_layer(input)
print(output)
tensor([[[[211., 262.],
          [251., 169.]]]], grad_fn=<ConvolutionBackward0>)

2 最大池化层

最大池化层是卷积神经网络中常用的一种池化层,用于对输入特征图进行降采样,从而减小特征图的尺寸和参数数量,同时保留特征图中的主要特征。

最大池化层的操作非常简单:对于每个池化窗口,它会输出窗口内的最大值作为窗口的输出。因此,最大池化层没有任何需要学习的参数,只需要指定池化窗口的大小和步长。

在最大池化层中,池化窗口通常采用2×2大小,步长为2,这种池化方式也被称为2倍下采样。例如,在一个2×2的池化窗口中,选取4个输入值中的最大值作为池化窗口的输出值。最大池化层可以有效地减少输入特征图的尺寸和参数数量,从而加速网络的训练和推理过程,并且在一定程度上可以降低过拟合的风险。

image-20230416001053808

import torch

input = [3, 4, 6, 5,
         2, 4, 6, 8,
         1, 6, 7, 5,
         9, 7, 4, 6]
input = torch.tensor(input, dtype=torch.float).view(1, 1, 4, 4)
maxpooling_layer = torch.nn.MaxPool2d(kernel_size=2)  #池化层,池化核大小2*2,步长默认为池化核大小
output = maxpooling_layer(input)
print(output)
tensor([[[[4., 8.],
          [9., 7.]]]])

3 手写数字识别

过程:

image-20230416001320582

image-20230416001443988

下面是一个使用PyTorch实现的简单的卷积神经网络,包含了数据集的准备、模型的设计、损失函数和优化器的构建以及训练和测试的过程。

该模型采用了两个卷积层和一个全连接层,每个卷积层后接一个最大池化层。其中第一个卷积层的输入通道为1,输出通道为10,卷积核大小为 5 x 5;第二个卷积层的输入通道为10,输出通道为20,卷积核大小仍为 5 x 5;两个池化层的窗口大小均为 2 x 2;全连接层的输入大小为320,输出大小为10,表示10个类别的概率分布。

模型的训练采用了SGD优化器,学习率为0.01,动量为0.5,损失函数为交叉熵损失函数。在训练过程中,每隔300个batch打印一次平均loss,并在每个epoch结束后进行一次测试,计算模型在测试集上的准确率。训练过程一共进行了10个epoch。

import torch
import torch.nn.functional as F
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt

# 1、准备数据集
batch_size = 64
transform = transforms.Compose([  # 一系列的操作,Compose将其组合在一起
    transforms.ToTensor(),  # 将图片转换为Tensor
    transforms.Normalize((0.1307,), (0.3081,))  # 标准化到[0,1],均值和方差
])
train_dataset = datasets.MNIST(root='../P6 逻辑斯谛回归/data',
                               train=True,
                               download=False,  # 在P6 逻辑斯谛回归中我已下载,这里直接读取即可
                               transform=transform)
test_dataset = datasets.MNIST(root='../P6 逻辑斯谛回归/data',
                              train=False,
                              download=False,
                              transform=transform)
train_loader = DataLoader(dataset=train_dataset,
                          batch_size=batch_size,
                          shuffle=True)
test_loader = DataLoader(dataset=test_dataset,
                         batch_size=batch_size,
                         shuffle=False)  # 测试集设置为False,方便观察结果


# 2、设计模型
class Net(torch.nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = torch.nn.Conv2d(1, 10, kernel_size=5)  # 第一个卷积层
        self.conv2 = torch.nn.Conv2d(10, 20, kernel_size=5)  # 第二个卷积层
        self.mp = torch.nn.MaxPool2d(2)  # 池化层
        self.l1 = torch.nn.Linear(320, 10)  # 全连接层

    def forward(self, x):
        # Flatten data from (n, 1, 28, 28) to (n, 784)
        batch_size = x.size(0)  #获取batch_size,这里的batch_size=64
        x = F.relu(self.mp(self.conv1(x)))  # 第一个卷积层+池化层+激活函数
        x = F.relu(self.mp(self.conv2(x)))  # 第二个卷积层+池化层+激活函数
        x = x.view(batch_size, -1)  # 将数据展平,方便全连接层处理
        x = self.l1(x)  # 全连接层
        return x


model = Net()
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")  # 判断是否有GPU加速
model.to(device)  # 将模型放到GPU上

# 3、构建损失和优化器
criterion = torch.nn.CrossEntropyLoss()  # 交叉熵损失函数
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.5)  # 优化器,lr为学习率,momentum为动量


# 4、训练和测试
def train(epoch):
    running_loss = 0.0
    for batch_idx, data in enumerate(train_loader, 0):
        inputs, labels = data
        inputs, labels = inputs.to(device), labels.to(device)  # 将数据放到GPU上
        optimizer.zero_grad()  # 梯度清零
        # forward + backward + update
        outputs = model(inputs)  # outputs并不是概率,而是线性层的输出,但其大小顺序与概率分布相同
        loss = criterion(outputs, labels)
        loss.backward()  # 反向传播
        optimizer.step()  # 更新参数

        running_loss += loss.item()
        if batch_idx % 300 == 299:  # 每300个batch打印一次平均loss
            print('[%d, %5d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 300))
            running_loss = 0.0


def test():
    correct = 0
    total = 0
    with torch.no_grad():  # 测试过程中不需要计算梯度
        for data in test_loader:
            images, labels = data
            images, labels = images.to(device), labels.to(device)  # 将数据放到GPU上
            outputs = model(images)
            _, predicted = torch.max(outputs.data, dim=1)  # 返回每一行中最大值的那个元素,以及其索引
            total += labels.size(0)  # labels的size为[64],即64个样本
            correct += (predicted == labels).sum().item()  # 统计预测正确的样本个数
    accuracy = 100 * correct / total
    accuracy_list.append(accuracy)
    print('Accuracy on test set: %d %%' % accuracy)


if __name__ == '__main__':
    accuracy_list = []
    for epoch in range(10):
        train(epoch)
        test()
    plt.plot(accuracy_list)
    plt.xlabel('epoch')
    plt.ylabel('accuracy')
    plt.grid()
    plt.show()
 

运行结果:

[1,   300] loss: 0.577
[1,   600] loss: 0.192
[1,   900] loss: 0.127
Accuracy on test set: 97 %
[2,   300] loss: 0.113
[2,   600] loss: 0.094
[2,   900] loss: 0.087
Accuracy on test set: 97 %
[3,   300] loss: 0.084
[3,   600] loss: 0.077
[3,   900] loss: 0.068
Accuracy on test set: 97 %
[4,   300] loss: 0.066
[4,   600] loss: 0.062
[4,   900] loss: 0.061
Accuracy on test set: 98 %
[5,   300] loss: 0.052
[5,   600] loss: 0.055
[5,   900] loss: 0.057
Accuracy on test set: 98 %
[6,   300] loss: 0.050
[6,   600] loss: 0.051
[6,   900] loss: 0.048
Accuracy on test set: 98 %
[7,   300] loss: 0.045
[7,   600] loss: 0.046
[7,   900] loss: 0.045
Accuracy on test set: 98 %
[8,   300] loss: 0.040
[8,   600] loss: 0.043
[8,   900] loss: 0.042
Accuracy on test set: 98 %
[9,   300] loss: 0.035
[9,   600] loss: 0.041
[9,   900] loss: 0.040
Accuracy on test set: 98 %
[10,   300] loss: 0.038
[10,   600] loss: 0.033
[10,   900] loss: 0.038
Accuracy on test set: 98 %

20230415

由于好奇增大epoch会怎么样,但我电脑没有GPU,就白嫖Kaggle的GPU跑了一下,把epoch增加到20,结果如下,可以跑到99%的准确率:
在这里插入图片描述
在这里插入图片描述

这个模型的训练和测试过程,可以考虑以下几个方面的改进:

  1. 数据增强:可以通过增加数据的随机变换(如旋转、缩放、平移等)来扩充训练集,从而增加模型的鲁棒性和泛化能力。
  2. 学习率调度:可以采用学习率调度策略(如StepLR、ReduceLROnPlateau等)来动态地调整学习率,从而使模型更容易收敛和避免过拟合。
  3. 权重初始化:可以采用不同的权重初始化方法(如Xavier、He等)来改善模型的收敛速度和效果。
  4. 正则化:可以通过L1/L2正则化、Dropout等方法来减轻过拟合的问题。
  5. 模型结构:可以尝试改变模型的层数、卷积核大小、池化层大小等超参数,从而提高模型的表现。
  6. 批归一化:可以在卷积层和全连接层之间添加批归一化层,从而加速模型收敛和提高泛化能力。
  7. 损失函数:可以采用不同的损失函数(如Focal Loss、Dice Loss等)来改善模型在不平衡数据集上的表现。

需要注意的是,每一种改进方式都需要根据具体情况进行选择和调整,同时还需要进行充分的实验验证,以确定其有效性和可行性。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringCloud之OpenFeign介绍案例+相关面试题

概述 OpenFeign是一个声明式的WEB服务客户端&#xff0c;它使WEB服务客户端变得更加容易。具有可插拔的注解支持&#xff0c;SpringCloud中添加了SpringMVC注解的支持。SpringCloud中集成了Ribbon和Eureka&#xff0c;以及SpringCloud LoadBalance&#xff0c;以便在使用Feign时…

C++数据结构:树

树 树是一种数据结构&#xff0c;它是n(n>0)个节点的有限集。n0时称为空树。n>0时&#xff0c;有限集的元素构成一个具有层次感的数据结构。 根 有且仅有一个结点的非空树&#xff0c;那个结点就是根。 A就是上面树的根节点 子树 在一棵非空树中&#xff0c;除根外&a…

由浅入深,一文彻底搞懂Mybatis+面试题分享

mybatis常见面试题链接&#xff1a;2023年-Mybatis常见面试题_是Smoky呢的博客-CSDN博客 MVC架构模式和三层架构 在说Mybatis之前&#xff0c;需要知道MVC架构模式和三层架构的这种思想 MVC架构模式 M&#xff1a;Model&#xff0c;数据层。都是和数据相关&#xff0c;比如实体…

MongoDB实现---事务机制

事务机制 原子性是MongoDB实现事务的难点&#xff0c;隔离性和持久性则是MongoDB事务机制的亮点 ACID支持&#xff1a;由于前面说过MongoDB是基于大数据、提供高度可扩展和高可用&#xff1b;所以其事务机制不仅仅是一般ACID还是结合了BASE理论下的ACID 原子性&#xff1a;保…

键盘录入及标识符

键盘录入 键盘录入介绍&#xff1a; ●为什么要有键盘录入? 目的&#xff1a;为了让我们操作的数据,变得更加灵活 举例&#xff1a;int a10; 这里a虽然是个变量&#xff0c;但记录的值&#xff0c;却是手动写死的。 提问&#xff1a;能不能让a变量记录的值&#xff0c;灵活…

Elasticsearch-mapping

1.Mapping基本概念 Mapping 也称之为映射&#xff0c;定义了 ES 的索引结构、字段类型、分词器等属性&#xff0c;是索引必不可少的组成部分。 ES 中的 mapping 有点类似与RDB中“表结构”的概念&#xff0c;在 MySQL 中&#xff0c;表结构里包含了字段名称&#xff0c;字段的…

# IMAGE - Image Perimeters

# IMAGE - Image Perimeters ## 题面翻译 ### 描述 给出一张由"x"和"."组成的矩阵。每个"x"可以向上下左右及两个斜对角进行连通&#xff0c;请问由某个点开始的"x"&#xff0c;它所连通的图形的周长为多少。 ### 输入 整个测试有多…

SpringBoot 整合ChatGPT API项目实战

准备工作 &#xff08;1&#xff09;已成功注册 OpenAI 的账号。 &#xff08;2&#xff09;创建 API KEY&#xff0c;这个 API KEY 是用于 HTTP 请求身份验证的&#xff0c;可以创建多个。 注意这个创建之后需要马上复制好保存&#xff0c;关闭弹框之后就看不到了。 &#xf…

excel的导入导出的两种方案 (1 EasyExcel 2 Hutool工具类)

文章目录 前言1 EasyExcel的导入导出导出1 导入依赖2 项目中的CourseEntity实体类3 CoureseVo VO类 (对CourseEntity进行EasyExcel导入导出操作)4 导出代码的编写 并最终测试导出效果5 (前端内容 可选)通过vue按钮点击 导出 导入1 导入依赖 跟导出相同2 创建回调监听器3 编写导…

1、Typescript基础入门与环境搭建

1、开发工具安装与基本配置 1.1、软件下载安装 如果你还没有使用过VSCode&#xff0c;当然先要去官网下载了。下载完成后双击安装&#xff0c;一直下一步即可。 1.2、编辑器汉化 如果你英语不是很好&#xff0c;配置中文版界面是很有必要的&#xff0c;安装个插件就可以了。打…

虚化背景 - 基于镜头模糊滤镜的深度映射

镜头模糊 Lens Blur等滤镜可以使用深度映射 Depth Map来设置像素在视觉上的前后关系。因此&#xff0c;常利用深度映射来创建真实感虚化效果&#xff0c;或者进行超越镜头的任意虚化处理。 ◆ ◆ ◆ 基于 Alpha 通道的深度映射关系 一般可通过建立 Alpha 通道或图层蒙版来创建…

【算法基础】DP第三弹 —— 竞赛篇

一、计数问题 (一)Question 1. 问题描述 2. Input 输入包含多组测试数据。每组测试数据占一行,包含两个整数 a 和 b。当读入一行为 0 0 时,表示输入终止,且该行不作处理。(0 < a, b < 100000000) 3. Output 每组数据输出一个结果,每个结果占一行。每个结果包…

MIPI D-PHYv2.5笔记(21) -- Forward High-Speed Data Transmission Timing

声明&#xff1a;作者是做嵌入式软件开发的&#xff0c;并非专业的硬件设计人员&#xff0c;笔记内容根据自己的经验和对协议的理解输出&#xff0c;肯定存在有些理解和翻译不到位的地方&#xff0c;有疑问请参考原始规范看 DDR时钟差分信号和Data差分信号的时序关系如下图所示…

计及调度经济性的光热电站储热容量配置方法【IEEE30节点】(Matlab代码实现)

&#x1f4a5; &#x1f4a5; &#x1f49e; &#x1f49e; 欢迎来到本博客 ❤️ ❤️ &#x1f4a5; &#x1f4a5; &#x1f3c6; 博主优势&#xff1a; &#x1f31e; &#x1f31e; &#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 …

计算机网络简史

ARPANET的发展 互联网最早的雏形 1931-ARPANET设计 互联网名人堂 1965-packet switching(分包交换) 1969 第一个RFC(Request for Comments)(开始通过APPANET发布)第一个接口信息处理单元&#xff08;Interface Message Processor&#xff09;&#xff08;下图&#xff0c;节…

ChatGPT时代:我们可能站到了自然语言编程的大门口

ChatGPT大火&#xff0c;我现在有种感觉&#xff1a;我们可能站到了自然语言编程的门口&#xff0c;一脚下去&#xff0c;也许能把门踹开。 当然&#xff0c;也可能会踢到一块铁板。 回顾我们的编程之路&#xff0c;基本上就是一个编程门槛不断降低的历史。 最早的一批前辈们…

wireshark抓包工具的使用

前言 ①wireshark是非常流行的网络封包分析软件&#xff0c;功能十分强大。可以截取各种网络封包&#xff0c;显示网络封包的详细信息。 ②使用wireshark的人必须了解网络协议&#xff0c;否则就看不懂wireshark。 ③为了安全考虑&#xff0c;wireshark只能查看封包&#xff…

【Linux】进程通信之管道通信详解

&#x1f34e;作者&#xff1a;阿润菜菜 &#x1f4d6;专栏&#xff1a;Linux系统编程 一、什么是管道通信 1. 管道通信是一种在进程间传递数据的方法 其实管道通信是Unix中最古老的进程间通信的形式了&#xff1a; 管道通信是一种进程间通信的方式&#xff0c;它可以让一个进…

聚观早报|马斯克将TruthGPT挑战ChatGPT;腾讯披露自研芯片新进展

今日要闻&#xff1a;马斯克将TruthGPT挑战ChatGPT&#xff1b;苹果在印度年销售额近60亿美元&#xff1b;腾讯披露自研芯片沧海最新进展&#xff1b;特斯拉中国工厂普通工人月薪约1万元&#xff1b;飞猪将直接向阿里CEO张勇汇报 马斯克将TruthGPT挑战ChatGPT 4 月 18 日消息&…

Pytorch深度学习笔记(四)梯度向下算法

课程推荐&#xff1a;03.梯度下降算法_哔哩哔哩_bilibili 优化问题&#xff1a;求误差值函数最小的权重w &#xff08;1&#xff09;梯度向下算法思想 在绝大多数的情况下&#xff0c;损失函数是很复杂的&#xff08;比如逻辑回归&#xff09;&#xff0c;根本无法得到参数估计…