构建一个简单 CNN 模型,通过加深模型深度、更改训练数据比例、调整训练参数等对比模型预测效果。

class CNNModel(nn.Module):
    def __init__(self, input_size, output_size, seq_length):
        super(CNNModel, self).__init__()
        hidden_channel=64
        out_channel=32
        
        kernel_size = 3
        stride = 1
        padding = 0
        self.conv1 = nn.Sequential(
            nn.Conv1d(in_channels=input_size, out_channels=hidden_channel, kernel_size=kernel_size),  # 24 - 2 + 1 = 23
            nn.ReLU()
            # nn.MaxPool1d(kernel_size=kernel_size, stride=stride), 
        )
        output_cnn = int((seq_length - kernel_size + 2*padding )/stride + 1)
        # output_pool = int((output_cnn - kernel_size + 2*padding )/stride + 1)
        self.Linear1 = nn.Linear(output_cnn*hidden_channel, output_size)
        self.conv2 = nn.Sequential(
            nn.Conv1d(in_channels=hidden_channel, out_channels=out_channel, kernel_size=kernel_size),  # 22 - 2 + 1 = 21
            nn.ReLU(),
            # nn.MaxPool1d(kernel_size=kernel_size, stride=stride),          
        )
        output_cnn = int((output_cnn - kernel_size + 2*padding )/stride + 1)
        # output_pool = int((output_cnn - kernel_size + 2*padding )/stride + 1)
        if output_cnn < 1:
            raise ValueError("seq_length 分配不足, 请扩大seq_length长度")
        self.Linear2 = nn.Linear(output_cnn*out_channel, output_size)
        self.relu = nn.ReLU(inplace=True)
    def forward(self, x, option=1):
        # x(batch_size, seq_len, input_size)
        x = x.permute(0, 2, 1)
        # x(batch_size, input_size, seq_len)
        if option == 1:
            x = self.conv1(x)
            # x = x.permute(0, 2, 1)
            x = x.reshape(x.shape[0], -1)
            x = self.Linear1(x)
        elif option == 2:
            x = self.conv1(x)
            x = self.conv2(x)
            x = x.reshape(x.shape[0], -1)
            x = self.Linear2(x)
        else:
            raise ValueError("option 输入不合法")
        return x

Conv1d 输入输出参数详解:

  • Input: (N,Cin,Lin)(N,C_{in},L_{in}) or (Cin,Lin)(C_{in},L_{in})

  • Output: (N,Cout,Lout)(N,C_{out},L_{out}) or (Cout,Lout)(C_{out},L_{out})

Lout=Lin+2×paddingdilation×(kernel_size1)1stride+1L_{out}=\lfloor \frac{L_{in}+2 \times padding-dilation \times (kernel\_size-1)-1}{stride} +1\rfloor

dilation: 1 (默认)

MaxPool1d 输入输出参数详解:

  • Input: (N,C,Lin)(N,C,L_{in}) or (C,Lin)(C,L_{in})

  • Output: (N,C,Lout)(N,C,L_{out}) or (C,Lout)(C,L_{out})

Lout=Lin+2×paddingdilation×(kernel_size1)1stride+1L_{out}=\lfloor \frac{L_{in}+2 \times padding-dilation \times (kernel\_size-1)-1}{stride} +1\rfloor

为了增加模型深度,取消了 maxpool

# 改变模型深度

只改变模型深度,加深 CNN 层,从 1 层加深到 2 层,对比查看测试图片效果,为了跟其他模型作对比,结合 seq_length 长度,这里最多只能进行两次卷积。

层数 活性数据 1 活性数据 2 色谱数据
1 iloc1_epoch100_seq7_layer1_predict iloc3_epoch100_seq7_layer1_predict iloc5_epoch100_seq7_layer1_predict
2 iloc1_epoch100_seq7_layer3_predict iloc3_epoch100_seq7_layer3_predict iloc5_epoch100_seq7_layer3_predict

🚩 加深网络模型并没有对预测数据产生大的影响,综合考量,我们接下来要以 2 层深度继续探讨改动其他参数的影响。

# 调整训练参数

主要修改的是 seq_length 长度

长度 活性数据 1 活性数据 2 色谱数据
7 iloc1_epoch100_seq7_layer2_predict iloc3_epoch100_seq7_layer2_predict iloc5_epoch100_seq7_layer2_predict
9 iloc1_epoch100_seq9_layer2_predict iloc3_epoch100_seq9_layer2_predict iloc5_epoch100_seq9_layer2_predict
11 iloc1_epoch100_seq11_layer2_predict iloc3_epoch100_seq11_layer2_predict iloc5_epoch100_seq11_layer5_predict
15 iloc1_epoch100_seq15_layer2_predict iloc3_epoch100_seq15_layer2_predict iloc5_epoch100_seq15_layer2_predict

🚩 增加 seq_length 长度,对活性数据影响不大,但对色谱数据有略微影响,尤其将 seq_length 长度增加到 15,出现了严重反方向预测,偏离了数据趋势增长方向。因此,我们将 seq_length 长度定义为 9,来继续探讨其他情况的影响。(这种情况跟 FNN 一样)

# 改变训练数据比例

只改变训练数据比例,5%,10%,15%,20% 的训练数据,训练数据分配情况参考 FNN改变训练数据比例 部分。本小节只展示不同训练比例对该模型的影响。

根据不同比例训练得到的结果图像如下所示:

比例 活性数据 1 活性数据 2 色谱数据
5 iloc1_epoch100_seq9_layer2_predict iloc3_epoch100_seq9_layer5_predict iloc5_epoch100_seq9_layer5_predict
10 iloc1_epoch100_seq9_layer5_predict iloc3_epoch100_seq9_layer5_predict iloc5_epoch100_seq9_layer5_predict
15 iloc1_epoch100_seq9_layer5_predict iloc3_epoch100_seq9_layer5_predict iloc5_epoch100_seq9_layer5_predict
20 iloc1_epoch100_seq9_layer5_predict iloc3_epoch100_seq9_layer5_predict iloc5_epoch100_seq9_layer5_predict

结合有效数据和上述预测图像分析,我们确定训练比例为原始数据的 5%