You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Keras/PyTorch构建含半固定Gabor滤波器的卷积神经网络?

当然没问题!不管是用PyTorch还是Keras,都能通过自定义卷积层来实现这种「一半固定Gabor滤波器+一半可学习滤波器」的CNN结构,完全贴合你提到的论文思路。下面我分别给出两种框架的具体实现方案:

PyTorch 实现方案

首先我们需要一个生成Gabor滤波器的工具函数,用来生成固定的滤波器组。Gabor的核心参数(方向、尺度、带宽等)可以根据你的任务需求调整:

import torch
import torch.nn as nn
import numpy as np

def generate_gabor_filters(kernel_size, num_filters, sigma=1.0, lambd=2.0, gamma=0.5):
    filters = []
    # 生成不同方向的Gabor滤波器
    for theta in np.linspace(0, np.pi, num_filters, endpoint=False):
        x, y = np.meshgrid(np.linspace(-(kernel_size//2), kernel_size//2, kernel_size),
                           np.linspace(-(kernel_size//2), kernel_size//2, kernel_size))
        # Gabor滤波器核心公式
        rot_x = x * np.cos(theta) + y * np.sin(theta)
        rot_y = -x * np.sin(theta) + y * np.cos(theta)
        gabor = np.exp(-(rot_x**2 + gamma**2 * rot_y**2)/(2*sigma**2)) * np.cos(2*np.pi*rot_x/lambd)
        # 归一化保证数值稳定
        gabor = (gabor - gabor.mean()) / gabor.std()
        filters.append(gabor)
    # 转为PyTorch卷积要求的张量形状 [num_filters, in_channels, kernel_size, kernel_size]
    filters = np.array(filters)[:, np.newaxis, :, :]
    return torch.tensor(filters, dtype=torch.float32)

接下来自定义混合卷积层,初始化时把一半滤波器设为固定Gabor(禁止梯度更新),另一半设为可学习的随机初始化参数:

class GaborMixedConv2d(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size, stride=1, padding=0):
        super().__init__()
        self.in_channels = in_channels
        self.out_channels = out_channels
        self.kernel_size = kernel_size
        self.stride = stride
        self.padding = padding
        
        # 分配固定Gabor和可学习滤波器的数量
        num_gabor = out_channels // 2
        num_learnable = out_channels - num_gabor
        
        # 生成固定Gabor滤波器,设置requires_grad=False避免训练时更新
        self.gabor_filters = nn.Parameter(generate_gabor_filters(kernel_size, num_gabor), requires_grad=False)
        
        # 初始化可学习卷积权重,用Kaiming初始化保证训练稳定性
        self.learnable_weights = nn.Parameter(torch.randn(num_learnable, in_channels, kernel_size, kernel_size))
        nn.init.kaiming_normal_(self.learnable_weights, mode='fan_out', nonlinearity='relu')
        
        # 可选的偏置参数
        self.bias = nn.Parameter(torch.zeros(out_channels)) if out_channels > 0 else None

    def forward(self, x):
        # 处理多通道输入:将单通道Gabor滤波器复制到对应输入通道数
        if self.in_channels > 1:
            gabor_filters = self.gabor_filters.repeat(1, self.in_channels, 1, 1)
        else:
            gabor_filters = self.gabor_filters
        
        # 拼接固定和可学习滤波器
        all_filters = torch.cat([gabor_filters, self.learnable_weights], dim=0)
        
        # 执行卷积操作
        out = nn.functional.conv2d(x, all_filters, bias=self.bias, stride=self.stride, padding=self.padding)
        return out

使用示例

# 构建一个简单的分类CNN
model = nn.Sequential(
    GaborMixedConv2d(in_channels=3, out_channels=16, kernel_size=3, padding=1),
    nn.ReLU(),
    nn.MaxPool2d(2),
    nn.Conv2d(16, 32, 3, padding=1),
    nn.ReLU(),
    nn.AdaptiveAvgPool2d(1),
    nn.Flatten(),
    nn.Linear(32, 10)
)
Keras 实现方案

在Keras(TensorFlow后端)中,我们通过自定义Layer类来实现同样的逻辑:

首先还是生成Gabor滤波器的函数,注意要适配Keras的卷积权重格式:

import tensorflow as tf
from tensorflow.keras import layers, Model
import numpy as np

def generate_gabor_filters(kernel_size, num_filters, sigma=1.0, lambd=2.0, gamma=0.5):
    filters = []
    for theta in np.linspace(0, np.pi, num_filters, endpoint=False):
        x, y = np.meshgrid(np.linspace(-(kernel_size//2), kernel_size//2, kernel_size),
                           np.linspace(-(kernel_size//2), kernel_size//2, kernel_size))
        rot_x = x * np.cos(theta) + y * np.sin(theta)
        rot_y = -x * np.sin(theta) + y * np.cos(theta)
        gabor = np.exp(-(rot_x**2 + gamma**2 * rot_y**2)/(2*sigma**2)) * np.cos(2*np.pi*rot_x/lambd)
        gabor = (gabor - gabor.mean()) / gabor.std()
        filters.append(gabor)
    # 转为Keras卷积要求的形状 [kernel_size, kernel_size, in_channels, num_filters]
    filters = np.array(filters).transpose(1,2,0)[..., np.newaxis]
    return tf.convert_to_tensor(filters, dtype=tf.float32)

然后自定义混合卷积层:

class GaborMixedConv2D(layers.Layer):
    def __init__(self, out_channels, kernel_size, stride=1, padding='same', **kwargs):
        super().__init__(**kwargs)
        self.out_channels = out_channels
        self.kernel_size = kernel_size
        self.stride = stride
        self.padding = padding
        
        # 分配固定Gabor和可学习滤波器的数量
        self.num_gabor = out_channels // 2
        self.num_learnable = out_channels - self.num_gabor

    def build(self, input_shape):
        self.in_channels = input_shape[-1]
        
        # 生成固定Gabor滤波器,用tf.stop_gradient禁止梯度更新
        self.gabor_filters = tf.stop_gradient(
            # 复制到对应输入通道数
            tf.repeat(generate_gabor_filters(self.kernel_size, self.num_gabor), self.in_channels, axis=-2)
        )
        
        # 初始化可学习卷积权重
        self.learnable_weights = self.add_weight(
            shape=(self.kernel_size, self.kernel_size, self.in_channels, self.num_learnable),
            initializer='he_normal',
            trainable=True,
            name='learnable_weights'
        )
        
        # 初始化偏置参数
        self.bias = self.add_weight(
            shape=(self.out_channels,),
            initializer='zeros',
            trainable=True,
            name='bias'
        )
        super().build(input_shape)

    def call(self, inputs):
        # 拼接固定和可学习滤波器
        all_filters = tf.concat([self.gabor_filters, self.learnable_weights], axis=-1)
        
        # 执行卷积操作
        return tf.nn.conv2d(
            inputs,
            all_filters,
            strides=[1, self.stride, self.stride, 1],
            padding=self.padding.upper()
        ) + self.bias

使用示例

# 构建一个简单的图像分类模型
inputs = layers.Input(shape=(28,28,3))
x = GaborMixedConv2D(16, 3)(inputs)
x = layers.ReLU()(x)
x = layers.MaxPool2D()(x)
x = layers.Conv2D(32, 3, padding='same')(x)
x = layers.ReLU()(x)
x = layers.GlobalAveragePooling2D()(x)
outputs = layers.Dense(10, activation='softmax')(x)

model = Model(inputs, outputs)
model.summary()

内容的提问来源于stack exchange,提问作者Bihy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:03:54