U-Kan代码解释

self.H, self.W = img_size[0] // patch_size[0], img_size[1] // patch_size[1]

`self.H` 和 `self.W` 是类 `PatchEmbed` 的两个属性,它们分别代表图像在高度和宽度方向上划分的补丁数量。这里的计算使用了整除运算符 `//`。

- `img_size[0]` 和 `img_size[1]` 分别是图像的高度和宽度
- `patch_size[0]` 和 `patch_size[1]` 分别是每个补丁的高度和宽度

整除运算符 `//` 用于计算两个数相除的整数结果,即商的整数部分。因此,

`img_size[0] // patch_size[0]` 计算的是,给定图像的高度可以被多少个高度为 `patch_size[0]` 的补丁完全覆盖不计算余数。同理,

`img_size[1] // patch_size[1]` 计算的是图像的宽度可以被多少个宽度为 `patch_size[1]` 的补丁完全覆盖

例如,如果图像的高度是 224 像素,补丁的高度是 7 像素,那么 `self.H` 将会是 224 // 7 = 32。这意味着图像高度方向上可以划分出 32 个补丁。同理,如果图像的宽度是 224 像素,补丁的宽度也是 7 像素,那么 `self.W` 将会是 224 // 7 = 32,意味着图像宽度方向上也可以划分出 32 个补丁。

这样,`self.H` 和 `self.W` 就定义了图像被划分成多少行和多少列的补丁网格。
 

 def __init__(self, dim, drop=0., drop_path=0., act_layer=nn.GELU, norm_layer=nn.LayerNorm, no_kan=False):
  • drop_path: 路径Dropout率,用于正则化,防止过拟合。

路径Dropout,也称为Stochastic Depth,是一种用于深度神经网络的正则化技术,特别是对于深度残差网络(ResNet)及其变体。这种技术的目的是通过随机地丢弃网络中的某些路径来防止过拟合。

在标准的Dropout中,我们随机地将网络中的一些神经元的输出置为零,以减少神经元之间复杂的共适应关系。然而,在残差网络中,每个残差块(或单元)都会将输入直接添加到输出上,这意味着即使某些层被Dropout了,信息仍然可以通过残差连接传播。这使得Dropout在残差网络中的效果不如在其他类型的网络中那么有效。

路径Dropout解决这个问题的方法是,在训练过程中随机地丢弃整个残差块,而不是单个神经元。这意味着在每次前向传播时,网络中的某些层将完全被跳过,而其他层则正常工作。这样,网络的深度在每次训练迭代中都是变化的,这迫使网络学习到更加鲁棒的特征表示,因为它们必须在不同的网络深度配置下仍然有效。

使用路径Dropout可以带来以下好处:
- **提高泛化能力**:通过随机丢弃路径,模型不会对特定的路径过度依赖,从而提高模型对新数据的泛化能力。
- **减少过拟合**:由于每次训练的网络结构都略有不同,这有助于打破对称性,减少过拟合的风险。
- **提高训练效率**:在某些情况下,路径Dropout可以提高训练速度,因为它减少了每次迭代中需要计算的参数数量。

总的来说,路径Dropout是一种有效的技术,可以在保持网络深度的同时,提高模型的泛化能力和训练效率。
 

  def _init_weights(self, m):

        if isinstance(m, nn.Linear):
            trunc_normal_(m.weight, std=.02)
            if isinstance(m, nn.Linear) and m.bias is not None:
                nn.init.constant_(m.bias, 0)

        elif isinstance(m, nn.LayerNorm):
            nn.init.constant_(m.bias, 0)
            nn.init.constant_(m.weight, 1.0)
            
        elif isinstance(m, nn.Conv2d):
            fan_out = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
            fan_out //= m.groups
            m.weight.data.normal_(0, math.sqrt(2.0 / fan_out))
            if m.bias is not None:
                m.bias.data.zero_()

这段代码定义了一个名为`_init_weights`的函数,它用于初始化神经网络中的权重。这个函数是`KANBlock`类的一部分,并且被应用于类的子模块。下面是对函数中每一部分的详细解释:

1. `def _init_weights(self, m):` 定义了一个方法,它接受一个参数`m`,这个参数代表当前正在初始化的模块

2. `if isinstance(m, nn.Linear):` 检查模块`m`是否是`nn.Linear`类型的实例,即线性层。

3. `trunc_normal_(m.weight, std=.02)` 如果是线性层,使用截断正态分布初始化权重。截断正态分布是一种初始化方法,它确保权重的值在正态分布的一定范围内,这里标准差是0.02

4. `if isinstance(m, nn.Linear) and m.bias is not None:` 进一步检查如果该线性层有偏置项(`bias`)。
   - `nn.init.constant_(m.bias, 0)` 将偏置项初始化为0。

5. `elif isinstance(m, nn.LayerNorm):` 检查模块`m`是否是`nn.LayerNorm`类型的实例,即层归一化层
   - `nn.init.constant_(m.bias, 0)` 将层归一化层的偏置项初始化为0。
   - `nn.init.constant_(m.weight, 1.0)` 将层归一化层的权重(增益参数)初始化为1.0,这样在归一化之后,原始数据的均值变为0,标准差变为1,然后乘以1.0,输出值不变。

6. `elif isinstance(m, nn.Conv2d):` 检查模块`m`是否是`nn.Conv2d`类型的实例,即二维卷积层

7. `fan_out = m.kernel_size[0] * m.kernel_size[1] * m.out_channels` 计算卷积核的扇出值,即卷积核的尺寸乘以输出通道数。

8. `fan_out //= m.groups` 如果卷积层使用了分组(grouped convolution),则将扇出值除以组数。

9. `m.weight.data.normal_(0, math.sqrt(2.0 / fan_out))` 使用正态分布初始化卷积层的权重,均值为0,标准差为`sqrt(2.0 / fan_out)`。这是一种启发式初始化方法,用于保持卷积层的输出在训练开始时具有稳定的方差。

10. `if m.bias is not None:` 检查卷积层是否有偏置项。
    - `m.bias.data.zero_()` 如果有偏置项,则将其初始化为0。

权重初始化是深度学习中的一个重要步骤,正确的初始化方法可以帮助模型更快地收敛,并减少训练初期的不稳定性。这段代码中使用的初始化方法考虑了不同类型的层,为它们提供了适合的初始化策略。
 

U-KAN  Architecture

Convolution Phrase卷积阶段       

      

Tokenized KAN Phrase(标记化的Kan阶段)

Tokenization:

Embedding by KAN Layer

   

U-KAN Decoder

 Extending U-KAN to Diffusion Models

代码部分 

网格:

在机器学习和计算机视觉等领域,"网格"(Grid)通常是指将数据空间划分为一个由多个子区域组成的结构,这些子区域可以帮助更好地理解、分析或操作数据。

关于Kan,KANLayer,这是一个自定义的线性层

class KANLayer(nn.Module):
    def __init__(self, in_features, hidden_features=None, out_features=None, act_layer=nn.GELU, drop=0., no_kan=False):
        super().__init__()
        out_features = out_features or in_features
        hidden_features = hidden_features or in_features
        self.dim = in_features
        
        #
        grid_size=5
        spline_order=3
        scale_noise=0.1
        scale_base=1.0
        scale_spline=1.0
        base_activation=torch.nn.SiLU
        grid_eps=0.02
        grid_range=[-1, 1]

这些参数是为自定义的 `KANLinear` 层提供的,控制着该层的网格大小、样条曲线的行为、噪声比例等特性。每个参数在 `KANLayer` 类的 `__init__` 方法中都有定义和用途。下面是对这些参数的详细解释:

 `grid_size=5`
- **含义**: 网格大小指特征空间中用于划分数据的网格数量。
- **作用**: 在一些模型中,特征空间被分割为多个网格单元,`grid_size` 决定了这些网格的维度或划分的细致程度。较大的 `grid_size` 通常意味着更精细的特征划分。

 `spline_order=3`
- **含义**: 样条曲线的阶数(order)。
- **作用**: 样条曲线用于平滑或拟合数据,`spline_order` 决定了样条的复杂度。阶数为 3 的样条曲线即三次样条曲线(cubic spline),它能够提供更平滑的曲线拟合效果。

. `scale_noise=0.1`
- **含义**: 噪声比例(scale noise)。
- **作用**: 在模型中引入噪声以增强其泛化能力,`scale_noise` 决定了噪声的强度。较高的噪声比例可能有助于防止过拟合,但也可能降低模型的精度。

 `scale_base=1.0`
- **含义**: 基础比例(scale base)。
- **作用**: 用于缩放基础特征的比例。这个参数通常用于调整模型中特定特征的影响程度,以便在训练过程中平衡不同特征的权重。

### 5. `scale_spline=1.0`
- **含义**: 样条曲线比例(scale spline)。
- **作用**: 调整样条曲线的影响程度。`scale_spline` 可以用来控制样条曲线对特征变换的影响力度,从而影响特征的映射方式

### 6. `base_activation=torch.nn.SiLU`
- **含义**: 基础激活函数。
- **作用**: 指定了在 `KANLinear` 层中使用的激活函数类型。`SiLU`(Sigmoid Linear Unit)是一种激活函数,它将输入乘以其 sigmoid 函数值。这种激活函数在一些神经网络模型中表现良好。

### 7. `grid_eps=0.02`
- **含义**: 网格的微小扰动(epsilon)。
- **作用**: 用于在网格边界上添加微小的扰动,以避免数值计算中的边界问题。`grid_eps` 通常用于防止由于数值精度限制而导致的计算错误。

### 8. `grid_range=[-1, 1]`
- **含义**: 网格范围。
- **作用**: 定义了网格在特征空间中的取值范围。`grid_range=[-1, 1]` 表示网格的每个维度的值在 -1 到 1 之间,这个范围决定了模型如何处理输入数据的空间映射。

前向传播

def forward(self, x, H, W):

        # pdb.set_trace()

        B, N, C = x.shape

        x = self.fc1(x.reshape(B*N,C))

        x = x.reshape(B,N,C).contiguous()

        x = self.dwconv_1(x, H, W)

        x = self.fc2(x.reshape(B*N,C))

        x = x.reshape(B,N,C).contiguous()

        x = self.dwconv_2(x, H, W)

        x = self.fc3(x.reshape(B*N,C))

        x = x.reshape(B,N,C).contiguous()

        x = self.dwconv_3(x, H, W)

        # # TODO

        # x = x.reshape(B,N,C).contiguous()

        # x = self.dwconv_4(x, H, W)

        return x

UKAN的神经网络模型

 

  • 18
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值