pytorch学习day4

一、卷积层(Convolution Layers)

卷积层是卷积神经网络(CNN)中的核心组件,用于提取输入数据的特征。它们通过应用卷积运算来捕捉局部的空间特征,非常适合处理图像和视频等具有空间结构的数据。

1. 卷积层的基本概念

卷积层通过在输入图像上滑动一个小的卷积核(也称为滤波器),计算每个位置的加权和来生成特征图。卷积核的权重是可以学习的参数,通过训练数据进行优化。

主要参数:

  • 输入通道数(in_channels):输入数据的通道数。例如,RGB图像的通道数为3。
  • 输出通道数(out_channels):卷积层输出的通道数,即卷积核的数量。
  • 卷积核大小(kernel_size):卷积核的空间尺寸,通常是一个整数(例如3表示3x3的卷积核)或一个元组(例如(3, 3))。
  • 步幅(stride):卷积核在输入上滑动的步长。默认值为1。
  • 填充(padding):在输入的边缘补充零,使卷积核可以在边缘处理。默认值为0。

2. PyTorch中的二维卷积层(nn.Conv2d)

代码示例:

import torch
import torch.nn as nn

# 定义一个二维卷积层
conv_layer = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=3, stride=1, padding=1)

# 创建一个输入张量,形状为(批量大小, 通道数, 高度, 宽度)
input_tensor = torch.randn(1, 3, 32, 32)

# 通过卷积层处理输入张量
output_tensor = conv_layer(input_tensor)

print(output_tensor.shape)

# 提取第一个通道的特征图
feature_map = outputimg[0, 0, :, :].detach().numpy()

# 可视化特征图
plt.imshow(feature_map, cmap='gray')
plt.colorbar()
plt.title('Feature Map')
plt.show()

在这个示例中,我们定义了一个卷积层,输入通道数为3,输出通道数为16,卷积核大小为3x3,步幅为1,填充为1。输入张量为一个随机生成的32x32的RGB图像。卷积层处理输入张量后,输出张量的形状为(1, 16, 32, 32)。

详细解释:

  • 输入通道数(in_channels):卷积层接收输入数据的深度。例如,对于RGB图像,深度为3。
  • 输出通道数(out_channels):卷积层生成的特征图的深度。每个卷积核会产生一个特征图。
  • 卷积核大小(kernel_size):定义卷积核的高度和宽度。例如,3x3卷积核会考虑3x3区域内的像素。
  • 步幅(stride):决定卷积核在输入图像上滑动的步长。步幅越大,输出特征图的尺寸越小。
  • 填充(padding):在输入图像的边缘添加额外的像素,以便卷积核能够处理图像边缘。填充越多,输出特征图的尺寸越大。

3. nn.Conv2d对数据进行读取和卷积

import torch
import torch.nn as  nn
import matplotlib.pyplot as plt
import os
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
from PIL import Image
from torchvision import transforms

def transform_invert(img_tensor, transform):
    """
    反转图像的预处理操作
    :param img_tensor: 经过预处理的图像张量
    :param transform: 预处理操作
    :return: 反转预处理操作后的图像
    """
    if 'Normalize' in str(transform):
        mean = torch.tensor(transform.transforms[1].mean)
        std = torch.tensor(transform.transforms[1].std)
        img_tensor = img_tensor * std[:, None, None] + mean[:, None, None]
    img_tensor = img_tensor.squeeze()  # 移除批量维度
    img = transforms.ToPILImage()(img_tensor)  # 转换为PIL图像
    return img

# ================================= load img ==================================
# 定义图像预处理变换
transform = transforms.Compose([
    # transforms.Resize((128, 128)),  # 调整图像大小
    # transforms.RandomHorizontalFlip(),  # 随机水平翻转
    # transforms.RandomRotation(10),  # 随机旋转10度
    # transforms.ColorJitter(brightness=0.5),  # 随机改变亮度
    transforms.ToTensor(),  # 转换为张量并归一化到[0, 1]
    transforms.Normalize((0.5,), (0.5,))  # 用均值0.5和标准差0.5归一化
])

# 加载图像
image = Image.open("taylorpicture.jpg").convert("RGB")

# 应用预处理变换
transformed_image = transform(image)

# 检查变换后的图像
print(transformed_image.size())
# image.show()

# 转换为张量
img_transform = transforms.Compose([transforms.ToTensor()])
img_tensor = img_transform(image)


# 添加 batch 维度
img_tensor.unsqueeze_(dim=0)




# =============== create convolution layer ==================

# 定义一个二维卷积层
input_convd = nn.Conv2d(in_channels=3, out_channels=1, kernel_size=3)

nn.init.xavier_normal_(input_convd.weight.data)


# 通过卷积层处理输入张量
img_conv = input_convd(img_tensor)

print(img_conv.shape)

# ================================= visualization ==================================
print("卷积前尺寸:{}\n卷积后尺寸:{}".format(img_tensor.shape, img_conv.shape))
img_conv = transform_invert(img_conv[0, 0:1, ...], img_transform)
img_raw = transform_invert(img_tensor.squeeze(), img_transform)
plt.subplot(122).imshow(img_conv, cmap='gray')
plt.subplot(121).imshow(img_raw)
plt.show()

卷积前,图像尺寸是464×580, 卷积后, 图像尺寸是462×578。我们这里的卷积核设置, 输入通道3, 卷积核个数1, 卷积核大小3, 无padding,步长是1, 那么我们根据上面的公式, 输出尺寸:(464−3)/1+1=462   (580−3)/1+1=578

torch.Size([3, 464, 580])
torch.Size([1, 1, 462, 578])
卷积前尺寸:torch.Size([1, 3, 464, 580])
卷积后尺寸:torch.Size([1, 1, 462, 578])

 3.1 增加 batch 维度

img_tensor.unsqueeze_(dim=0) 

这行代码使用unsqueeze_方法在张量的第0维添加一个新的维度。unsqueeze_方法是原地操作,会直接修改img_tensor而不是返回一个新的张量。

在此之前,img_tensor只有通道、高度和宽度。为了让这个张量能够作为输入传递给卷积神经网络模型,我们通常需要一个包含批量大小的维度(batch size)。卷积神经网络的输入通常是四维张量,形状为 [batch_size, channels, height, width]。通过在第0维添加一个维度,这里的1表示批量大小,即一次处理一个图像。

3.2 增加卷积权值初始化

在这段代码中,nn.init.xavier_normal_ 使用了Xavier正态分布来初始化卷积层的权重。这种初始化方法使得每个卷积核中的权重值根据一个正态分布随机生成,分布的标准差根据输入和输出的通道数进行计算,确保每一层输出的方差稳定。

总结:通过这些操作,可以确保图像正确加载为张量,并以适合卷积神经网络输入的格式传递。

4. nn.ConvTranspose 转置卷积

转置卷积(Transposed Convolution)也称为反卷积(Deconvolution),是一种用于上采样(Upsampling)的操作,通常用于生成对原始输入分辨率更高的特征图。转置卷积最常用于生成对抗网络(GANs)和语义分割等需要将低分辨率特征图恢复到高分辨率的任务中。

转置卷积的作用

  1. 上采样:转置卷积可以将特征图的分辨率放大,从而恢复到原始输入的尺寸。这对于图像生成和分割任务非常重要。
  2. 特征重建:它可以帮助重建原始图像的细节,通过将低分辨率特征图恢复到高分辨率。
  3. 反向传播有效性:转置卷积允许有效的梯度反向传播,从而使得网络能够学习到有效的特征。

PyTorch 中的 nn.ConvTranspose2d

PyTorch 提供了 nn.ConvTranspose2d 类,用于实现二维转置卷积。其参数与普通卷积类似,包括输入通道数、输出通道数、卷积核大小等。

参数介绍

  • in_channels:输入特征图的通道数。
  • out_channels:输出特征图的通道数。
  • kernel_size:卷积核的大小,可以是单个整数或者元组。
  • stride:卷积核的步幅,决定了上采样的倍数。
  • padding:在输入图像四周填充的像素数。
  • output_padding:输出图像额外的填充,控制输出尺寸。
  • bias:是否使用偏置,默认为True。

示例代码

以下示例展示了如何定义和使用二维转置卷积层:

import torch
import torch.nn as  nn
import matplotlib.pyplot as plt
import os
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
from PIL import Image
from torchvision import transforms

def transform_invert(img_tensor, transform):
    """
    反转图像的预处理操作
    :param img_tensor: 经过预处理的图像张量
    :param transform: 预处理操作
    :return: 反转预处理操作后的图像
    """
    if 'Normalize' in str(transform):
        mean = torch.tensor(transform.transforms[1].mean)
        std = torch.tensor(transform.transforms[1].std)
        img_tensor = img_tensor * std[:, None, None] + mean[:, None, None]
    img_tensor = img_tensor.squeeze()  # 移除批量维度
    img = transforms.ToPILImage()(img_tensor)  # 转换为PIL图像
    return img

# ================================= load img ==================================
# 定义图像预处理变换
transform = transforms.Compose([
    # transforms.Resize((128, 128)),  # 调整图像大小
    # transforms.RandomHorizontalFlip(),  # 随机水平翻转
    # transforms.RandomRotation(10),  # 随机旋转10度
    # transforms.ColorJitter(brightness=0.5),  # 随机改变亮度
    transforms.ToTensor(),  # 转换为张量并归一化到[0, 1]
    transforms.Normalize((0.5,), (0.5,))  # 用均值0.5和标准差0.5归一化
])

# 加载图像
image = Image.open("taylorpicture.jpg").convert("RGB")

# 应用预处理变换
transformed_image = transform(image)

# 检查变换后的图像
print(transformed_image.size())
# image.show()

# 转换为张量
img_transform = transforms.Compose([transforms.ToTensor()])
img_tensor = img_transform(image)


# 添加 batch 维度
img_tensor.unsqueeze_(dim=0)




# =============== create convolution layer ==================

# 定义一个二维卷积层
input_convd = nn.ConvTranspose2d(in_channels=3, out_channels=1, kernel_size=3,stride=1)

nn.init.xavier_normal_(input_convd.weight.data)


# 通过卷积层处理输入张量
img_conv = input_convd(img_tensor)

print(img_conv.shape)

# ================================= visualization ==================================
print("卷积前尺寸:{}\n卷积后尺寸:{}".format(img_tensor.shape, img_conv.shape))
img_conv = transform_invert(img_conv[0, 0:1, ...], img_transform)
img_raw = transform_invert(img_tensor.squeeze(), img_transform)
plt.subplot(122).imshow(img_conv, cmap='gray')
plt.subplot(121).imshow(img_raw)
plt.show()

输出解释

  1. 当然,以下是可以直接复制的转置卷积输出尺寸计算公式:

    Hout​=(Hin​−1)×stride+kernel_size−2×padding+output_padding

    Wout​=(Win​−1)×stride+kernel_size−2×padding+output_padding

    在这段代码中,

  2. 应用公式计算输出尺寸:

    Hout​=(464−1)×1+3−2×0+0=464+2=466

    Wout​=(580−1)×1+3−2×0+0=580+2=582

    因此,输入尺寸为 torch.Size([1, 3, 464, 580]) 的图像通过转置卷积层后,输出尺寸变为 torch.Size([1, 1, 466, 582])

转置卷积的数学原理

转置卷积可以理解为将卷积操作反转。普通卷积是通过卷积核在输入上滑动并计算加权和,转置卷积则是将输入的每个元素反向传播到输出,通过插值(通常是零填充)来扩展尺寸。具体实现中,转置卷积可以通过对输入进行零填充并进行标准卷积实现。

5. 卷积层的优点

参数共享

卷积层中的卷积核在整个输入图像上共享相同的权重参数,这大大减少了需要训练的参数数量,从而减轻了过拟合的风险,并提高了计算效率。

局部感受野

卷积核只处理输入图像的局部区域,这使得卷积层能够有效捕捉局部特征,如边缘、纹理和角点等。

平移不变性

由于卷积运算在整个图像上进行滑动,卷积层具有一定的平移不变性,能够识别图像中同一特征的不同位置。

二、池化层(Convolution Layers)

1.池化层介绍

池化层(Pooling Layer)是卷积神经网络(CNN)中的一种常见操作,通常用于减少数据的空间维度(即宽度和高度),从而减少参数数量和计算量,同时保留重要的特征信息。

主要类型的池化层

  1. 最大池化(Max Pooling)

    • 在池化窗口内取最大值,主要用于提取最显著的特征。
    • 公式: [ Y(i, j) = \max(X_{i:i+f, j:j+f}) ] 其中 X 是输入特征图,f 是池化窗口大小,Y 是输出特征图。
  2. 平均池化(Average Pooling)

    • 在池化窗口内取平均值,用于平滑特征图。
    • 公式: [ Y(i, j) = \frac{1}{f^2} \sum_{m=0}^{f-1} \sum_{n=0}^{f-1} X(i+m, j+n) ] 其中 X 是输入特征图,f 是池化窗口大小,Y 是输出特征图。

池化层参数

池化层的主要参数包括:

  • 池化窗口大小(Kernel Size or Pool Size):通常为 2×2 或 3×3。
  • 步幅(Stride):决定池化窗口在输入特征图上滑动的步长,通常与池化窗口大小相同。
  • 填充(Padding):决定是否在输入特征图周围添加零填充,通常池化层不使用填充。

池化层效果展示

上图展示了池化层(Pooling Layer)的操作:

  • 左侧:输入图像,尺寸为 4×4,每个格子中的数字代表像素值。
  • 右侧:经过最大池化(Max Pooling)后的输出图像,尺寸为 2×2。在每个 2×2 的池化窗口内,取最大值作为输出。

输入图像中的数值经过最大池化后,每个池化窗口内的最大值被提取出来,形成一个更小的输出图像。这种操作减少了图像的空间尺寸,同时保留了重要的特征信息。

2.池化层函数nn.MaxPool2d

nn.MaxPool2d 详细解释:

nn.MaxPool2d 是 PyTorch 中用于实现二维最大池化操作的函数。

参数
  • kernel_size: 池化窗口的大小,可以是一个整数或一个整数元组。例如,kernel_size=2 或 kernel_size=(2, 2)
  • stride: 步幅,窗口在输入张量上滑动的步长。默认为 kernel_size 的大小。如果步幅和池化窗口的大小相同,则不会重叠。如果步幅小于窗口大小,则会有重叠。
  • padding: 填充,在输入张量的边缘补零的数量。默认为0,即不填充。
  • dilation: 空洞池化中的扩张率,默认为1。
  • return_indices: 如果设为 True,会返回最大值的索引。通常用于最大池化的反向操作(如 nn.MaxUnpool2d)。
  • ceil_mode: 如果设为 True,则在计算输出大小时使用上取整,而不是默认的下取整。
import torch
import torch.nn as  nn
import matplotlib.pyplot as plt
import os
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
from PIL import Image
from torchvision import transforms

def transform_invert(img_tensor, transform):
    """
    反转图像的预处理操作
    :param img_tensor: 经过预处理的图像张量
    :param transform: 预处理操作
    :return: 反转预处理操作后的图像
    """
    if 'Normalize' in str(transform):
        mean = torch.tensor(transform.transforms[1].mean)
        std = torch.tensor(transform.transforms[1].std)
        img_tensor = img_tensor * std[:, None, None] + mean[:, None, None]
    img_tensor = img_tensor.squeeze()  # 移除批量维度
    img = transforms.ToPILImage()(img_tensor)  # 转换为PIL图像
    return img

# ================================= load img ==================================
# 定义图像预处理变换
transform = transforms.Compose([
    # transforms.Resize((128, 128)),  # 调整图像大小
    # transforms.RandomHorizontalFlip(),  # 随机水平翻转
    # transforms.RandomRotation(10),  # 随机旋转10度
    # transforms.ColorJitter(brightness=0.5),  # 随机改变亮度
    transforms.ToTensor(),  # 转换为张量并归一化到[0, 1]
    transforms.Normalize((0.5,), (0.5,))  # 用均值0.5和标准差0.5归一化
])

# 加载图像
image = Image.open("taylorpicture.jpg").convert("RGB")

# 应用预处理变换
transformed_image = transform(image)

# 检查变换后的图像
print(transformed_image.size())
# image.show()

# 转换为张量
img_transform = transforms.Compose([transforms.ToTensor()])
img_tensor = img_transform(image)


# 添加 batch 维度
img_tensor.unsqueeze_(dim=0)




# =============== create convolution layer ==================

# 定义一个二维卷积层
maxpool_layer = nn.MaxPool2d((2, 2), stride=(2, 2))

# 通过卷积层处理输入张量
img_conv = maxpool_layer(img_tensor)

print(img_conv.shape)

# ================================= visualization ==================================
print("卷积前尺寸:{}\n卷积后尺寸:{}".format(img_tensor.shape, img_conv.shape))
img_conv = transform_invert(img_conv[0, 0:1, ...], img_transform)
img_raw = transform_invert(img_tensor.squeeze(), img_transform)
plt.subplot(122).imshow(img_conv, cmap='gray')
plt.subplot(121).imshow(img_raw)
plt.show()
torch.Size([3, 464, 580])
torch.Size([1, 3, 232, 290])
卷积前尺寸:torch.Size([1, 3, 464, 580])
卷积后尺寸:torch.Size([1, 3, 232, 290])

从输入尺寸和输出尺寸的变化,我们可以推测池化层的参数:

假设使用最大池化层 nn.MaxPool2d 进行操作,且池化窗口大小为 2x2,那么可以计算步幅和池化窗口的参数。

计算步幅和池化窗口大小

假设我们使用 kernel_size=2stride=2,即池化窗口为2x2,步幅为2,则可以通过以下公式计算输出尺寸:

Hout​=⌊strideHin​−kernel_size​⌋/stride+1

Wout​=⌊strideWin​−kernel_size​⌋/stride+1

应用公式计算实例

假设输入张量的高度和宽度分别为 464 和 580,使用 kernel_size=2stride=2 的最大池化层:

计算高度(Height):

Hout​=⌊464−2​⌋/2+1=⌊231⌋+1=232

计算宽度(Width):

Wout​=⌊580−2​⌋/2+1=⌊289⌋+1=290

3.池化层函数nn.AvgPool2d

nn.AvgPool2d 详细解释

nn.AvgPool2d 是 PyTorch 中用于实现二维平均池化操作的函数。

参数
  • kernel_size: 池化窗口的大小,可以是一个整数或一个整数元组。例如,kernel_size=2 或 kernel_size=(2, 2)
  • stride: 步幅,窗口在输入张量上滑动的步长。默认为 kernel_size 的大小。如果步幅和池化窗口的大小相同,则不会重叠。如果步幅小于窗口大小,则会有重叠。
  • padding: 填充,在输入张量的边缘补零的数量。默认为0,即不填充。
  • ceil_mode: 如果设为 True,则在计算输出大小时使用上取整,而不是默认的下取整。
  • count_include_pad: 如果设为 True,将计算填充在内,否则不计算填充。
import torch
import torch.nn as  nn
import matplotlib.pyplot as plt
import os
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
from PIL import Image
from torchvision import transforms

def transform_invert(img_tensor, transform):
    """
    反转图像的预处理操作
    :param img_tensor: 经过预处理的图像张量
    :param transform: 预处理操作
    :return: 反转预处理操作后的图像
    """
    if 'Normalize' in str(transform):
        mean = torch.tensor(transform.transforms[1].mean)
        std = torch.tensor(transform.transforms[1].std)
        img_tensor = img_tensor * std[:, None, None] + mean[:, None, None]
    img_tensor = img_tensor.squeeze()  # 移除批量维度
    img = transforms.ToPILImage()(img_tensor)  # 转换为PIL图像
    return img

# ================================= load img ==================================
# 定义图像预处理变换
transform = transforms.Compose([
    # transforms.Resize((128, 128)),  # 调整图像大小
    # transforms.RandomHorizontalFlip(),  # 随机水平翻转
    # transforms.RandomRotation(10),  # 随机旋转10度
    # transforms.ColorJitter(brightness=0.5),  # 随机改变亮度
    transforms.ToTensor(),  # 转换为张量并归一化到[0, 1]
    transforms.Normalize((0.5,), (0.5,))  # 用均值0.5和标准差0.5归一化
])

# 加载图像
image = Image.open("taylorpicture.jpg").convert("RGB")

# 应用预处理变换
transformed_image = transform(image)

# 检查变换后的图像
print(transformed_image.size())
# image.show()

# 转换为张量
img_transform = transforms.Compose([transforms.ToTensor()])
img_tensor = img_transform(image)


# 添加 batch 维度
img_tensor.unsqueeze_(dim=0)




# =============== create convolution layer ==================

# 定义一个二维卷积层
AvgPool_layer = nn.AvgPool2d((2, 2), stride=(2, 2))

# 通过卷积层处理输入张量
img_conv = AvgPool_layer(img_tensor)

print(img_conv.shape)

# ================================= visualization ==================================
print("卷积前尺寸:{}\n卷积后尺寸:{}".format(img_tensor.shape, img_conv.shape))
img_conv = transform_invert(img_conv[0, 0:1, ...], img_transform)
img_raw = transform_invert(img_tensor.squeeze(), img_transform)
plt.subplot(122).imshow(img_conv, cmap='gray')
plt.subplot(121).imshow(img_raw)
plt.show()
torch.Size([3, 464, 580])
torch.Size([1, 3, 232, 290])
卷积前尺寸:torch.Size([1, 3, 464, 580])
卷积后尺寸:torch.Size([1, 3, 232, 290])

4.池化层函数nn.MaxUnpool2d

nn.MaxUnpool2d 详细解释

nn.MaxUnpool2d 是 PyTorch 中用于实现二维最大池化的反操作(反池化)的函数。反池化用于将池化后的特征图恢复到池化前的尺寸,通常与 nn.MaxPool2d 一起使用,以便在一些网络结构(如自编码器或生成对抗网络)中进行上采样操作。

参数
  • kernel_size: 反池化窗口的大小,可以是一个整数或一个整数元组。例如,kernel_size=2 或 kernel_size=(2, 2)
  • stride: 步幅,窗口在输入张量上滑动的步长。默认为 kernel_size 的大小。
  • padding: 填充,在输入张量的边缘补零的数量。默认为0,即不填充。
import torch
import torch.nn as nn

# 定义输入张量
input_tensor = torch.tensor([[[[1, 2, 3, 4],
                               [5, 6, 7, 8],
                               [9, 10, 11, 12],
                               [13, 14, 15, 16]]]], dtype=torch.float32)

# 定义最大池化层
max_pool = nn.MaxPool2d(kernel_size=2, stride=2, return_indices=True)

# 应用最大池化层
output_max_pool, indices = max_pool(input_tensor)

print("Max pooling output:")
print(output_max_pool)
print("Indices of max values:")
print(indices)

# 定义最大池化反操作层
max_unpool = nn.MaxUnpool2d(kernel_size=2, stride=2)

# 应用最大池化反操作层
output_unpool = max_unpool(output_max_pool, indices, output_size=input_tensor.shape)

print("Unpooled output (after MaxUnpool2d):")
print(output_unpool)
tensor([[[[ 6.,  8.],
          [14., 16.]]]])
Indices of max values:
tensor([[[[ 5,  7],
          [13, 15]]]])
Unpooled output (after MaxUnpool2d):
tensor([[[[ 0.,  0.,  0.,  0.],
          [ 0.,  6.,  0.,  8.],
          [ 0.,  0.,  0.,  0.],
          [ 0., 14.,  0., 16.]]]])

这里的参数与池化层是类似的。唯一的不同就是前向传播的时候我们需要传进一个indices, 我们的索引值,要不然不知道把输入的元素放在输出的哪个位置上。

三、线性层—Linear Layer

线性层(Linear Layer)是神经网络中的基本层之一,通常用于全连接网络或密集层。在 PyTorch 中,线性层由 nn.Linear 类实现。线性层执行的是线性变换,它将输入向量乘以一个权重矩阵,并加上一个偏置向量。

线性层的定义和操作

线性层的操作可以用以下数学公式表示:

y = 𝒙𝑾𝑻 + 𝒃𝒊𝒂𝒔 

其中:

  • x 是输入向量或输入张量。
  • W 是权重矩阵。
  • b 是偏置向量。
  • y 是输出向量或输出张量。

nn.Linear 详细解释

参数
  • in_features: 输入特征的数量。
  • out_features: 输出特征的数量。
  • bias: 如果设置为 False,层将不会学习偏置。默认值为 True。

示例代码

以下示例代码展示了如何使用 nn.Linear 定义和应用线性层:

import torch
import torch.nn as nn

# 定义输入张量
input_tensor = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]], dtype=torch.float32)

# 打印输入张量形状
print(f"Input tensor shape: {input_tensor.shape}")

# 定义线性层
linear_layer = nn.Linear(in_features=3, out_features=2)

# 打印线性层权重和偏置
print("Initial weights:")
print(linear_layer.weight)
print("Initial bias:")
print(linear_layer.bias)

# 应用线性层
output_tensor = linear_layer(input_tensor)

# 打印输出张量形状
print(f"Output tensor shape: {output_tensor.shape}")

# 打印输出张量
print(f"Output tensor: \n{output_tensor}")

解释

  1. 输入张量:形状为 (2, 3),表示有两个样本,每个样本有3个特征。
  2. 线性层:定义一个线性层,将3个输入特征映射到2个输出特征。
  3. 权重和偏置:线性层包含一个权重矩阵和一个偏置向量。权重矩阵的形状为 (2, 3),偏置向量的形状为 (2,)
  4. 输出张量:形状为 (2, 2),表示经过线性层后的输出,每个样本有2个输出特征。

详细代码解释

  • 输入张量

    input_tensor = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]], dtype=torch.float32)

    输入张量的形状为 (2, 3),表示有两个样本,每个样本有3个特征。

  • 定义线性层

    linear_layer = nn.Linear(in_features=3, out_features=2)

    定义一个线性层,将3个输入特征映射到2个输出特征。

  • 打印线性层权重和偏置

    print("Initial weights:")
    print(linear_layer.weight)
    print("Initial bias:")
    print(linear_layer.bias)

  • 应用线性层

    output_tensor = linear_layer(input_tensor)

  • 打印输出张量

    print(f"Output tensor: \n{output_tensor}")

    运行结果

    Input tensor shape: torch.Size([2, 3])
    Initial weights:
    Parameter containing:
    tensor([[-0.5265, -0.2825,  0.4228],
            [ 0.0674, -0.0214,  0.0749]], requires_grad=True)
    Initial bias:
    Parameter containing:
    tensor([-0.4118, -0.1031], requires_grad=True)
    Output tensor shape: torch.Size([2, 2])
    Output tensor: 
    tensor([[-0.2350,  0.1464],
            [-1.3938,  0.5094]], grad_fn=<AddmmBackward0>)
    
    Process finished with exit code 0
    

总结

线性层是神经网络中的基本构建块,通常用于将输入特征映射到输出特征。通过定义输入和输出特征的数量,可以使用 nn.Linear 创建线性层,并将其应用到输入张量上,执行线性变换。这个过程在神经网络的训练和推理中非常常见,是许多复杂网络结构的基础。

 四、激活函数层—Activate Layer

激活函数层(Activation Layer)是神经网络中的关键组件,用于引入非线性特性,使网络能够学习和表示复杂的函数。常见的激活函数包括 ReLU、Sigmoid、Tanh 等。在 PyTorch 中,激活函数可以通过 torch.nn.functionaltorch.nn 模块来使用。

常见激活函数

  1. ReLU(Rectified Linear Unit)
  2. Sigmoid
  3. Tanh(Hyperbolic Tangent)
  4. Leaky ReLU
  5. Softmax

1. ReLU(Rectified Linear Unit)

ReLU 是一种简单且常用的激活函数,它将输入中的负值置为零,正值保持不变。

示例代码:

import torch
import torch.nn.functional as F

# 定义输入张量
input_tensor = torch.tensor([[-1.0, 2.0, -3.0], [4.0, -5.0, 6.0]])

# 应用 ReLU 激活函数
output_tensor = F.relu(input_tensor)

print("ReLU activation output:")
print(output_tensor)

2. Sigmoid

Sigmoid 函数将输入映射到 (0, 1) 的区间内,常用于二分类问题。

示例代码:

# 应用 Sigmoid 激活函数
output_tensor = torch.sigmoid(input_tensor)

print("Sigmoid activation output:")
print(output_tensor)

3. Tanh(Hyperbolic Tangent)

Tanh 函数将输入映射到 (-1, 1) 的区间内。

示例代码:

# 应用 Tanh 激活函数
output_tensor = torch.tanh(input_tensor)

print("Tanh activation output:")
print(output_tensor)

4. Leaky ReLU

Leaky ReLU 是 ReLU 的一种变体,它允许负值有一个小的斜率,以解决 ReLU 的“神经元死亡”问题。

示例代码:

# 应用 Leaky ReLU 激活函数
leaky_relu = torch.nn.LeakyReLU(0.01)
output_tensor = leaky_relu(input_tensor)

print("Leaky ReLU activation output:")
print(output_tensor)

5. Softmax

Softmax 函数通常用于多分类问题的最后一层,它将输入转换为概率分布。

示例代码:

# 应用 Softmax 激活函数
output_tensor = F.softmax(input_tensor, dim=1)

print("Softmax activation output:")
print(output_tensor)

详细代码解释

以下是一个综合示例,展示如何在一个简单的神经网络中使用这些激活函数:

import torch
import torch.nn as nn
import torch.nn.functional as F

class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()
        self.fc1 = nn.Linear(3, 5)
        self.fc2 = nn.Linear(5, 2)
        
    def forward(self, x):
        x = self.fc1(x)
        x = F.relu(x)  # 使用 ReLU 激活函数
        x = self.fc2(x)
        x = torch.sigmoid(x)  # 使用 Sigmoid 激活函数
        return x

# 定义输入张量
input_tensor = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]], dtype=torch.float32)

# 创建简单神经网络实例
model = SimpleNN()

# 前向传播
output_tensor = model(input_tensor)

print("Output tensor:")
print(output_tensor)

6. PReLU

nn.PReLU 详细解释

nn.PReLU 是 PyTorch 中的 Parametric Rectified Linear Unit(参数化线性修正单元)层。Parametric ReLU 是 Leaky ReLU 的一种扩展,它允许神经网络学习激活函数中的负斜率,而不是固定地设置为一个小的常数。这意味着神经网络可以根据数据动态地学习激活函数的形状。

参数
  • num_parameters: 定义 PReLU 中需要学习的负斜率的数量,通常设置为1以学习一个共享的负斜率。

示例代码

import torch
import torch.nn as nn

# 定义输入张量
input_tensor = torch.tensor([-1.0, 2.0, -3.0], dtype=torch.float32)

# 定义 Parametric ReLU 层
prelu = nn.PReLU(num_parameters=1)

# 应用 Parametric ReLU
output_tensor = prelu(input_tensor)

# 打印输出张量
print("Parametric ReLU output:")
print(output_tensor)

在这个示例中,nn.PReLU 层被用来应用 Parametric ReLU 激活函数到输入张量上。这允许神经网络按照数据的需求学习负斜率。

总结

激活函数层在神经网络中起到引入非线性特性的作用,使得网络能够学习复杂的模式和函数。PyTorch 提供了多种激活函数,可以根据具体任务选择合适的激活函数来构建和训练神经网络。

  • 22
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值