File size: 5,176 Bytes
8e3369b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import torch
import torch.nn as nn
import torch.nn.init as init
import warnings

import torch.nn.functional as F
warnings.filterwarnings('ignore')


class CAFN(nn.Module):
    def __init__(self, input_dim=46, num_classes=4, hidden_size=128): # --- 新增了 hidden_size 参数 ---
        super(CAFN, self).__init__()

        self.conv_layer11 = nn.Sequential(
            nn.Conv1d(in_channels=1, out_channels=32, kernel_size=3),
            nn.ReLU(),
            nn.MaxPool1d(kernel_size=2)
        )
        self.conv_layer12 = nn.Sequential(
            nn.Conv1d(in_channels=3, out_channels=32, kernel_size=5),
            nn.ReLU(),
            nn.MaxPool1d(kernel_size=2)
        )

        self.conv_layer1 = nn.Sequential(
            nn.Conv1d(in_channels=64, out_channels=64, kernel_size=3),
            nn.ReLU(),
            nn.MaxPool1d(kernel_size=2)
        )
        self.conv_layer2 = nn.Sequential(
            nn.Conv1d(in_channels=64, out_channels=64, kernel_size=3),
            nn.ReLU(),
            nn.MaxPool1d(kernel_size=2)
        )
        self.conv_layer3 = nn.Sequential(
            nn.Conv1d(in_channels=64, out_channels=64, kernel_size=3),
            nn.ReLU(),
            nn.MaxPool1d(kernel_size=2)
        )

        # --- 删除了原有的分类头 ---
        # self.conv_layer_w = nn.Sequential(...)
        # self.flatten = nn.Flatten()
        # self.fc_layer = nn.Sequential(...)

        # --- 新增 biGRU 层 ---
        self.hidden_size = 64
        self.biGRU = nn.GRU(
            input_size=64,           # 输入特征维度,即CNN输出的通道数
            hidden_size=hidden_size, # GRU隐藏层维度,可调超参
            num_layers=1,            # GRU层数,增加层数可以学习更复杂的模式
            bidirectional=True,      # 开启双向
            batch_first=True,        # 输入数据格式为 (batch, seq, feature)
        )

        # --- 新增一个全连接层,用于最终分类 ---
        self.dropout_gru = nn.Dropout(0.15)
        self.fc_gru = nn.Linear(hidden_size * 2, num_classes) # *2 是因为双向

        self.apply(self.init_weights)
        self.Residual = MSRN()

    def init_weights(self, m):
        if type(m) == nn.Conv1d or type(m) == nn.Linear:
            init.xavier_uniform_(m.weight)
            if m.bias is not None:
                init.constant_(m.bias, 0.0)
        # --- 新增对GRU权重的初始化(可选,但推荐) ---
        elif type(m) == nn.GRU:
            for name, param in m.named_parameters():
                if 'weight_ih' in name:
                    init.xavier_uniform_(param.data)
                elif 'weight_hh' in name:
                    init.orthogonal_(param.data)
                elif 'bias' in name:
                    param.data.fill_(0)


    def forward(self, x1, x2):
        '''

        x1: PSTAAP

        x2: PhysicoChemical

        '''
        device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
        x1 = x1.to(device)
        x1 = x1.unsqueeze(1)
        x1 = self.conv_layer11(x1)
        _, w1 = self.Residual(x1)  # (batch_size, 64, 4)

        x2 = x2.to(device)
        x2 = x2.transpose(1, 2)
        x2 = self.conv_layer12(x2)
        _, w2 = self.Residual(x2)  # (batch_size, 64, 4)

        w = torch.cat((w1, w2), dim=2)  # (batch_size, 64, 8)

        x = w.permute(0, 2, 1)
        self.biGRU.flatten_parameters()
        output, _ = self.biGRU(x) # output shape: (batch, seq_len, hidden_size * 2)

        forward_out = output[:, -1, :self.hidden_size]
        backward_out = output[:, 0, self.hidden_size:]
        x = torch.cat((forward_out, backward_out), dim=1) # (batch, hidden_size * 2)
        x = self.dropout_gru(x)
        x = self.fc_gru(x) # (batch, num_classes)

        return x



class MSRN(nn.Module):
    def __init__(self, input_dim=46, num_classes=4):
        super(MSRN, self).__init__()

        self.conv_layer1 = nn.Sequential(
            nn.Conv1d(in_channels=32, out_channels=32, kernel_size=3),
            nn.ReLU(),
            nn.Dropout(0.2),
            nn.MaxPool1d(kernel_size=2)
        )

        self.conv_layer2 = nn.Sequential(
            nn.Conv1d(in_channels=32, out_channels=64, kernel_size=3),
            nn.ReLU(),
            nn.Dropout(0.2),
            nn.MaxPool1d(kernel_size=2)
        )

        self.conv_layer3 = nn.Sequential(
            nn.Conv1d(in_channels=64, out_channels=64, kernel_size=3),
            nn.ReLU(),
            nn.Dropout(0.2),
            nn.MaxPool1d(kernel_size=2)
        )

        self.apply(self.init_weights)

    def init_weights(self, m):
        if type(m) == nn.Conv1d or type(m) == nn.Linear:

            init.xavier_uniform_(m.weight)
            if m.bias is not None:

                init.constant_(m.bias, 0.0)

    def forward(self, x):
        x1 = self.conv_layer1(x)  # (64,10)
        x2 = self.conv_layer2(x1)  # (64,4)
        w1 = x2
        x3 = self.conv_layer3(x2)  # (64,1)
        return x3, w1