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 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
| """ VOC 红外光谱深度学习识别系统
论文核心: 1. FTIR实验采集9种VOC光谱 2. CVAE合成增强训练数据 3. CNN分类器:识别VOC类别 + 预测浓度 4. 两头设计:分类头 + 回归头 """
import torch import torch.nn as nn import numpy as np from typing import Tuple, Optional
class VOCSpectraClassifier(nn.Module): """ VOC红外光谱分类器 两头设计: - 分类头:9类VOC识别 - 回归头:浓度预测 输入:FTIR吸收光谱(400-5000 cm^-1, 2301点) """ def __init__( self, input_length: int = 2301, num_classes: int = 9, hidden_dim: int = 256 ): super().__init__() self.feature_extractor = nn.Sequential( nn.Conv1d(1, 32, kernel_size=7, stride=2, padding=3), nn.BatchNorm1d(32), nn.ReLU(), nn.MaxPool1d(2), nn.Conv1d(32, 64, kernel_size=5, stride=1, padding=2), nn.BatchNorm1d(64), nn.ReLU(), nn.MaxPool1d(2), nn.Conv1d(64, 128, kernel_size=3, stride=1, padding=1), nn.BatchNorm1d(128), nn.ReLU(), nn.MaxPool1d(2), nn.Conv1d(128, hidden_dim, kernel_size=3, stride=1, padding=1), nn.BatchNorm1d(hidden_dim), nn.ReLU(), nn.AdaptiveAvgPool1d(1) ) self.classification_head = nn.Sequential( nn.Linear(hidden_dim, hidden_dim // 2), nn.ReLU(), nn.Dropout(0.3), nn.Linear(hidden_dim // 2, num_classes) ) self.regression_head = nn.Sequential( nn.Linear(hidden_dim, hidden_dim // 2), nn.ReLU(), nn.Dropout(0.3), nn.Linear(hidden_dim // 2, 1), nn.Softplus() ) def forward(self, spectra: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]: """ Args: spectra: (B, 1, L) FTIR吸收光谱 Returns: logits: (B, 9) VOC分类 concentration: (B, 1) 浓度预测 (ppm) """ features = self.feature_extractor(spectra) features = features.squeeze(-1) logits = self.classification_head(features) concentration = self.regression_head(features) return logits, concentration
class ConditionalVAE(nn.Module): """ 条件变分自编码器 (CVAE) 生成合成VOC光谱用于数据增强 条件:VOC类别 + 浓度 """ def __init__( self, input_length: int = 2301, latent_dim: int = 128, num_classes: int = 9, cond_dim: int = 32 ): super().__init__() self.latent_dim = latent_dim self.class_embed = nn.Embedding(num_classes, cond_dim) self.conc_embed = nn.Sequential( nn.Linear(1, cond_dim), nn.ReLU() ) self.encoder = nn.Sequential( nn.Conv1d(1, 32, 7, 2, 3), nn.ReLU(), nn.Conv1d(32, 64, 5, 2, 2), nn.ReLU(), nn.Conv1d(64, 128, 3, 2, 1), nn.ReLU(), nn.AdaptiveAvgPool1d(1), ) total_cond = cond_dim * 2 self.fc_mu = nn.Linear(128 + total_cond, latent_dim) fc_logvar = nn.Linear(128 + total_cond, latent_dim) self.decoder_input = nn.Linear(latent_dim + total_cond, 128 * (input_length // 8)) self.decoder = nn.Sequential( nn.ConvTranspose1d(128, 64, 4, 2, 1), nn.ReLU(), nn.ConvTranspose1d(64, 32, 4, 2, 1), nn.ReLU(), nn.ConvTranspose1d(32, 1, 4, 2, 1), ) def encode(self, x, class_idx, conc): h = self.encoder(x).squeeze(-1) c = torch.cat([ self.class_embed(class_idx), self.conc_embed(conc.unsqueeze(-1)) ], dim=-1) h = torch.cat([h, c], dim=-1) return self.fc_mu(h), self.fc_logvar(h) def reparameterize(self, mu, logvar): std = torch.exp(0.5 * logvar) eps = torch.randn_like(std) return mu + eps * std def decode(self, z, class_idx, conc): c = torch.cat([ self.class_embed(class_idx), self.conc_embed(conc.unsqueeze(-1)) ], dim=-1) h = self.decoder_input(torch.cat([z, c], dim=-1)) h = h.view(-1, 128, -1) return self.decoder(h) def forward(self, x, class_idx, conc): mu, logvar = self.encode(x, class_idx, conc) z = self.reparameterize(mu, logvar) recon = self.decode(z, class_idx, conc) return recon, mu, logvar def generate(self, class_idx, conc, device='cpu'): """生成指定类别和浓度的合成光谱""" z = torch.randn(class_idx.size(0), self.latent_dim).to(device) return self.decode(z, class_idx, conc)
if __name__ == "__main__": torch.manual_seed(42) spectra = torch.randn(4, 1, 2301) classifier = VOCSpectraClassifier() logits, conc = classifier(spectra) print("VOC分类器:") print(f" 输入: {spectra.shape}") print(f" 分类logits: {logits.shape}") print(f" 浓度预测: {conc.shape}") cvae = ConditionalVAE() class_idx = torch.tensor([0, 1, 2, 3]) conc_vals = torch.tensor([5.0, 10.0, 3.0, 20.0]) synthetic = cvae.generate(class_idx, conc_vals) print(f"\nCVAE合成光谱: {synthetic.shape}") print(f" 可生成指定VOC类别+浓度的合成光谱") params = sum(p.numel() for p in classifier.parameters()) print(f"\n分类器参数: {params:,} ({params/1e6:.2f}M)")
|