Coverage for robustAI/advertrain/models.py: 42%
198 statements
« prev ^ index » next coverage.py v7.9.2, created at 2025-10-01 08:42 +0000
« prev ^ index » next coverage.py v7.9.2, created at 2025-10-01 08:42 +0000
1import torch
2from torch import Tensor, nn
3from torch.nn import functional as F
5from robustAI.advertrain.dependencies.dropblock import DropBlock2d
8class Normalize(nn.Module):
9 def __init__(self, mean: Tensor, std: Tensor, device: torch.device) -> None:
10 """
11 Initialize the Normalize module.
13 This module is used to normalize image data by subtracting the mean and
14 dividing by the standard deviation.
16 Args:
17 mean (Tensor): A tensor containing the mean values for each channel.
18 std (Tensor): A tensor containing the standard deviation for each channel.
19 device (torch.device): The device (CPU or GPU) to which the tensors should be moved.
20 """
21 super().__init__()
23 self.mean = mean.unsqueeze(-1).unsqueeze(-1).to(device)
24 self.std = std.unsqueeze(-1).unsqueeze(-1).to(device)
26 def forward(self, x: Tensor) -> Tensor:
27 """
28 Normalize the input tensor.
30 Applies the normalization operation on the input tensor using the mean and
31 standard deviation provided during initialization.
33 Args:
34 x (Tensor): The input tensor to be normalized.
36 Returns:
37 Tensor: The normalized tensor.
38 """
39 return (x - self.mean) / self.std
42class ConvNet(nn.Module):
43 """
44 Convolutional Neural Network with dropout layers, designed for processing images of size 64x128.
46 This network includes a normalization layer, several convolutional layers with
47 ReLU activation and max pooling, followed by fully connected layers with dropout
48 for regularization. It is suited for tasks like image classification where dropout
49 can help reduce overfitting.
51 Attributes:
52 norm (Normalize): Normalization layer to preprocess the input images.
53 conv1, conv2_1, conv3_1, conv4_1 (nn.Conv2d): Convolutional layers for feature extraction.
54 pooling (nn.MaxPool2d): Max pooling layer to reduce spatial dimensions.
55 activation (nn.ReLU): Activation function.
56 dropout (nn.Dropout): Dropout layer for regularization.
57 linear1, linear2, linear3 (nn.Linear): Fully connected layers for classification.
58 """
60 def __init__(self, device: torch.device, p: float = 0.2) -> None:
61 """
62 Initializes the ConvNetDropout model with dropout layers.
64 Args:
65 device (torch.device): The device to which the model and tensors should be moved.
66 p (float): Dropout probability. Default is 0.2.
67 """
68 super().__init__()
70 self.norm = Normalize(
71 torch.Tensor([0.4632, 0.4532, 0.4485]),
72 torch.Tensor([0.1646, 0.1759, 0.1739]),
73 device,
74 )
76 self.conv1 = nn.Conv2d(3, 32, 7, padding=3)
77 self.conv2_1 = nn.Conv2d(32, 64, 5, padding=2)
78 self.conv3_1 = nn.Conv2d(64, 128, 5, padding=2)
79 self.conv4_1 = nn.Conv2d(128, 256, 5, padding=2)
81 self.pooling = nn.MaxPool2d(2)
82 self.activation = nn.ReLU()
83 self.dropout = nn.Dropout(p=p)
85 self.linear1 = nn.Linear(4 * 8 * 256, 2048)
86 self.linear2 = nn.Linear(2048, 1024)
87 self.linear3 = nn.Linear(1024, 2)
89 self.to(device)
91 def forward(self, x: Tensor) -> Tensor:
92 """
93 Defines the forward pass of the ConvNetDropout.
95 The input tensor is processed through normalization, convolutional layers,
96 pooling layers, dropout layers, and fully connected layers sequentially to
97 produce the output tensor.
99 Args:
100 x (Tensor): Input tensor of shape (batch_size, 3, 64, 128).
102 Returns:
103 Tensor: Output tensor after processing through the network.
104 """
105 x = self.norm(x)
107 y = self.activation(self.conv1(x))
108 y = self.pooling(y)
110 y = self.activation(self.conv2_1(y))
111 y = self.pooling(y)
113 y = self.activation(self.conv3_1(y))
114 y = self.pooling(y)
116 y = self.activation(self.conv4_1(y))
117 y = self.pooling(y)
119 y = self.activation(self.linear1(torch.reshape(y, (-1, 4 * 8 * 256))))
120 y = self.dropout(y)
121 y = self.activation(self.linear2(y))
122 y = self.dropout(y)
123 y = self.linear3(y)
125 return y
128class ConvNetDropblock(nn.Module):
129 """
130 Convolutional Neural Network with DropBlock regularization, designed for processing images of size 64x128.
132 This network includes a normalization layer, several convolutional layers with
133 ReLU activation and max pooling, followed by fully connected layers with dropout
134 and DropBlock for regularization. It is suited for tasks like image classification
135 where advanced regularization techniques can help reduce overfitting.
137 Attributes:
138 norm (Normalize): Normalization layer to preprocess the input images.
139 conv1, conv2_1, conv3_1, conv4_1 (nn.Conv2d): Convolutional layers for feature extraction.
140 pooling (nn.MaxPool2d): Max pooling layer to reduce spatial dimensions.
141 activation (nn.ReLU): Activation function.
142 dropout (nn.Dropout): Dropout layer for regularization.
143 dropblock (DropBlock2d): DropBlock layer for structured dropout.
144 linear1, linear2, linear3 (nn.Linear): Fully connected layers for classification.
145 """
147 def __init__(self, device: torch.device, p: float = 0.2, drop_prob: float = 0.0, n_steps: int = 10) -> None:
148 """
149 Initializes the ConvNetDropblock model with DropBlock layers.
151 Args:
152 device (torch.device): The device (CPU or GPU) to which the model and tensors should be moved.
153 p (float): Dropout probability for the standard dropout layers. Default is 0.2.
154 drop_prob (float): Initial probability for DropBlock. Default is 0.1.
155 n_steps (int): Number of steps over which DropBlock probability should reach its maximum. Default is 10.
156 """
157 super().__init__()
159 self.norm = Normalize(
160 torch.Tensor([0.4632, 0.4532, 0.4485]),
161 torch.Tensor([0.1646, 0.1759, 0.1739]),
162 device,
163 )
165 self.conv1 = nn.Conv2d(3, 32, 7, padding=3)
166 self.conv2_1 = nn.Conv2d(32, 64, 5, padding=2)
167 self.conv3_1 = nn.Conv2d(64, 128, 5, padding=2)
168 self.conv4_1 = nn.Conv2d(128, 256, 5, padding=2)
170 self.pooling = nn.MaxPool2d(2)
171 self.activation = nn.ReLU()
172 self.dropout = nn.Dropout(p=p)
174 self.dropblock = DropBlock2d(drop_prob=drop_prob)
175 self.drop_prob = drop_prob
176 self.n_epochs = n_steps
177 self.epochs = 0
179 self.linear1 = nn.Linear(4 * 8 * 256, 2048)
180 self.linear2 = nn.Linear(2048, 1024)
181 self.linear3 = nn.Linear(1024, 2)
183 self.to(device)
185 def forward(self, x: Tensor) -> Tensor:
186 """
187 Defines the forward pass of the ConvNetDropblock.
189 The input tensor is processed through normalization, convolutional layers,
190 pooling layers, DropBlock layers, dropout layers, and fully connected layers
191 sequentially to produce the output tensor.
193 Args:
194 x (Tensor): Input tensor of shape.
196 Returns:
197 Tensor: Output tensor after processing through the network.
198 """
199 x = self.norm(x)
201 y = self.activation(self.conv1(x))
202 y = self.pooling(y)
203 y = self.dropblock(y)
205 y = self.activation(self.conv2_1(y))
206 y = self.pooling(y)
207 y = self.dropblock(y)
209 y = self.activation(self.conv3_1(y))
210 y = self.pooling(y)
211 y = self.dropblock(y)
213 y = self.activation(self.conv4_1(y))
214 y = self.pooling(y)
216 y = self.activation(self.linear1(torch.reshape(y, (-1, 4 * 8 * 256))))
217 y = self.dropout(y)
218 y = self.activation(self.linear2(y))
219 y = self.dropout(y)
220 y = self.linear3(y)
222 return y
225class ResNet(nn.Module):
226 """
227 A custom implementation of a Residual Network (ResNet) for processing images.
229 This network consists of multiple convolutional layers, each followed by batch normalization,
230 and some layers include dropout for regularization. The network uses skip connections
231 similar to a ResNet architecture, adding the output of one layer to another layer.
232 """
234 def __init__(self, device: torch.device, p: float = 0.2) -> None:
235 """
236 Initializes the ResNet model.
238 Args:
239 device (torch.device): The device to which the model and tensors should be moved.
240 """
241 super().__init__()
243 self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1)
244 self.conv1_bn = nn.BatchNorm2d(32)
245 self.conv2 = nn.Conv2d(32, 32, kernel_size=3, padding=1)
246 self.conv2_bn = nn.BatchNorm2d(32)
247 self.conv3 = nn.Conv2d(32, 32, kernel_size=3, padding=1)
248 self.conv3_drop = nn.Dropout2d(p=0.2)
249 self.conv3_bn = nn.BatchNorm2d(32)
251 self.conv4 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
252 self.conv4_bn = nn.BatchNorm2d(64)
253 self.conv5 = nn.Conv2d(64, 64, kernel_size=3, padding=1)
254 self.conv5_bn = nn.BatchNorm2d(64)
255 self.conv6 = nn.Conv2d(64, 64, kernel_size=3, padding=1)
256 self.conv6_drop = nn.Dropout2d(p=0.2)
257 self.conv6_bn = nn.BatchNorm2d(64)
259 self.conv7 = nn.Conv2d(64, 128, kernel_size=3, padding=1)
260 self.conv7_bn = nn.BatchNorm2d(128)
261 self.conv8 = nn.Conv2d(128, 128, kernel_size=3, padding=1)
262 self.conv8_bn = nn.BatchNorm2d(128)
263 self.conv9 = nn.Conv2d(128, 128, kernel_size=3, padding=1)
264 self.conv9_drop = nn.Dropout2d(p=p)
265 self.conv9_bn = nn.BatchNorm2d(128)
267 self.conv10 = nn.Conv2d(128, 256, kernel_size=3, padding=1)
268 self.conv10_bn = nn.BatchNorm2d(256)
269 self.conv11 = nn.Conv2d(256, 256, kernel_size=3, padding=1)
270 self.conv11_bn = nn.BatchNorm2d(256)
271 self.conv12 = nn.Conv2d(256, 256, kernel_size=3, padding=1)
272 self.conv12_drop = nn.Dropout2d(p=p)
273 self.conv12_bn = nn.BatchNorm2d(256)
275 self.fc1 = nn.Linear(256 * 8 * 16, 2048)
276 self.fc1_bn = nn.BatchNorm1d(2048)
277 self.fc2 = nn.Linear(2048, 2)
279 self.to(device)
281 def forward(self, inp: Tensor) -> Tensor:
282 """
283 Defines the forward pass of the ResNet.
285 The input tensor is processed through a series of convolutional layers with skip connections,
286 batch normalization, and dropout, followed by fully connected layers to produce the output tensor.
288 Args:
289 inp (Tensor): Input tensor of appropriate shape, typically matching the input size of the first
290 convolutional layer.
292 Returns:
293 Tensor: Output tensor after processing through the network.
294 """
295 res = F.relu(self.conv1_bn(self.conv1(inp)))
296 x = F.relu(self.conv2_bn(self.conv2(res)))
297 x = self.conv3_drop(self.conv3(x))
298 block1_out = F.relu(self.conv3_bn(F.max_pool2d(x + res, 2))) # 32x64
300 res = F.relu(self.conv4_bn(self.conv4(block1_out)))
301 x = F.relu(self.conv5_bn(self.conv5(res)))
302 x = self.conv6_drop(self.conv6(x))
303 block2_out = F.relu(self.conv6_bn(F.max_pool2d(x + res, 2))) # 16x32
305 res = F.relu(self.conv7_bn(self.conv7(block2_out)))
306 x = F.relu(self.conv8_bn(self.conv8(res)))
307 x = self.conv9_drop(self.conv9(x))
308 block3_out = F.relu(self.conv9_bn(F.max_pool2d(x + res, 2))) # 8x16
310 res = F.relu(self.conv10_bn(self.conv10(block3_out)))
311 x = F.relu(self.conv11_bn(self.conv11(res)))
312 x = F.relu(self.conv12_bn(self.conv12_drop(self.conv12(x + res))))
314 x = x.view(-1, 256 * 8 * 16)
315 x = F.relu(self.fc1_bn(self.fc1(x)))
316 x = F.dropout(x, training=self.training, p=0.2)
317 x = self.fc2(x)
318 return x
321class ResNetDropblock(nn.Module):
322 """
323 A custom implementation of a Residual Network (ResNet) for processing images.
325 This network consists of multiple convolutional layers, each followed by batch normalization,
326 and some layers include dropout for regularization. The network uses skip connections
327 similar to a ResNet architecture, adding the output of one layer to another layer.
328 """
330 def __init__(self, device: torch.device, p: float = 0.2, drop_prob: float = 0.0) -> None:
331 """
332 Initializes the ResNet model.
334 Args:
335 device (torch.device): The device to which the model and tensors should be moved.
336 """
337 super().__init__()
339 self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1)
340 self.conv1_bn = nn.BatchNorm2d(32)
341 self.conv2 = nn.Conv2d(32, 32, kernel_size=3, padding=1)
342 self.conv2_bn = nn.BatchNorm2d(32)
343 self.conv3 = nn.Conv2d(32, 32, kernel_size=3, padding=1)
344 self.conv3_drop = nn.Dropout2d(p=0.2)
345 self.conv3_bn = nn.BatchNorm2d(32)
347 self.conv4 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
348 self.conv4_bn = nn.BatchNorm2d(64)
349 self.conv5 = nn.Conv2d(64, 64, kernel_size=3, padding=1)
350 self.conv5_bn = nn.BatchNorm2d(64)
351 self.conv6 = nn.Conv2d(64, 64, kernel_size=3, padding=1)
352 self.conv6_drop = nn.Dropout2d(p=0.2)
353 self.conv6_bn = nn.BatchNorm2d(64)
355 self.conv7 = nn.Conv2d(64, 128, kernel_size=3, padding=1)
356 self.conv7_bn = nn.BatchNorm2d(128)
357 self.conv8 = nn.Conv2d(128, 128, kernel_size=3, padding=1)
358 self.conv8_bn = nn.BatchNorm2d(128)
359 self.conv9 = nn.Conv2d(128, 128, kernel_size=3, padding=1)
360 self.conv9_drop = nn.Dropout2d(p=p)
361 self.conv9_bn = nn.BatchNorm2d(128)
363 self.conv10 = nn.Conv2d(128, 256, kernel_size=3, padding=1)
364 self.conv10_bn = nn.BatchNorm2d(256)
365 self.conv11 = nn.Conv2d(256, 256, kernel_size=3, padding=1)
366 self.conv11_bn = nn.BatchNorm2d(256)
367 self.conv12 = nn.Conv2d(256, 256, kernel_size=3, padding=1)
368 self.conv12_drop = nn.Dropout2d(p=p)
369 self.conv12_bn = nn.BatchNorm2d(256)
371 self.dropblock = DropBlock2d(drop_prob=drop_prob)
372 self.drop_prob = drop_prob
374 self.fc1 = nn.Linear(256 * 8 * 16, 2048)
375 self.fc1_bn = nn.BatchNorm1d(2048)
376 self.fc2 = nn.Linear(2048, 2)
378 self.to(device)
380 def forward(self, inp: Tensor) -> Tensor:
381 """
382 Defines the forward pass of the ResNet.
384 The input tensor is processed through a series of convolutional layers with skip connections,
385 batch normalization, and dropout, followed by fully connected layers to produce the output tensor.
387 Args:
388 inp (Tensor): Input tensor of appropriate shape, typically matching the input size of the first
389 convolutional layer.
391 Returns:
392 Tensor: Output tensor after processing through the network.
393 """
394 res = F.relu(self.conv1_bn(self.conv1(inp)))
395 x = F.relu(self.conv2_bn(self.conv2(res)))
396 x = self.conv3_drop(self.conv3(x))
397 x = self.dropblock(x)
398 block1_out = F.relu(self.conv3_bn(F.max_pool2d(x + res, 2))) # 32x64
400 res = F.relu(self.conv4_bn(self.conv4(block1_out)))
401 x = F.relu(self.conv5_bn(self.conv5(res)))
402 x = self.conv6_drop(self.conv6(x))
403 x = self.dropblock(x)
404 block2_out = F.relu(self.conv6_bn(F.max_pool2d(x + res, 2))) # 16x32
406 res = F.relu(self.conv7_bn(self.conv7(block2_out)))
407 x = F.relu(self.conv8_bn(self.conv8(res)))
408 x = self.conv9_drop(self.conv9(x))
409 x = self.dropblock(x)
410 block3_out = F.relu(self.conv9_bn(F.max_pool2d(x + res, 2))) # 8x16
412 res = F.relu(self.conv10_bn(self.conv10(block3_out)))
413 x = F.relu(self.conv11_bn(self.conv11(res)))
414 x = F.relu(self.conv12_bn(self.conv12_drop(self.conv12(x + res))))
415 x = self.dropblock(x)
417 x = x.view(-1, 256 * 8 * 16)
418 x = F.relu(self.fc1_bn(self.fc1(x)))
419 x = F.dropout(x, training=self.training, p=0.2)
420 x = self.fc2(x)
421 return x