langvision 0.0.1__py3-none-any.whl → 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of langvision might be problematic. Click here for more details.

Files changed (41) hide show
  1. langvision/__init__.py +77 -2
  2. langvision/callbacks/base.py +166 -7
  3. langvision/cli/__init__.py +85 -0
  4. langvision/cli/complete_cli.py +319 -0
  5. langvision/cli/config.py +344 -0
  6. langvision/cli/evaluate.py +201 -0
  7. langvision/cli/export.py +177 -0
  8. langvision/cli/finetune.py +165 -48
  9. langvision/cli/model_zoo.py +162 -0
  10. langvision/cli/train.py +27 -13
  11. langvision/cli/utils.py +258 -0
  12. langvision/components/attention.py +4 -1
  13. langvision/concepts/__init__.py +9 -0
  14. langvision/concepts/ccot.py +30 -0
  15. langvision/concepts/cot.py +29 -0
  16. langvision/concepts/dpo.py +37 -0
  17. langvision/concepts/grpo.py +25 -0
  18. langvision/concepts/lime.py +37 -0
  19. langvision/concepts/ppo.py +47 -0
  20. langvision/concepts/rlhf.py +40 -0
  21. langvision/concepts/rlvr.py +25 -0
  22. langvision/concepts/shap.py +37 -0
  23. langvision/data/enhanced_datasets.py +582 -0
  24. langvision/model_zoo.py +169 -2
  25. langvision/models/lora.py +189 -17
  26. langvision/models/multimodal.py +297 -0
  27. langvision/models/resnet.py +303 -0
  28. langvision/training/advanced_trainer.py +478 -0
  29. langvision/training/trainer.py +30 -2
  30. langvision/utils/config.py +180 -9
  31. langvision/utils/metrics.py +448 -0
  32. langvision/utils/setup.py +266 -0
  33. langvision-0.1.0.dist-info/METADATA +50 -0
  34. langvision-0.1.0.dist-info/RECORD +61 -0
  35. {langvision-0.0.1.dist-info → langvision-0.1.0.dist-info}/WHEEL +1 -1
  36. langvision-0.1.0.dist-info/entry_points.txt +2 -0
  37. langvision-0.0.1.dist-info/METADATA +0 -463
  38. langvision-0.0.1.dist-info/RECORD +0 -40
  39. langvision-0.0.1.dist-info/entry_points.txt +0 -2
  40. langvision-0.0.1.dist-info/licenses/LICENSE +0 -21
  41. {langvision-0.0.1.dist-info → langvision-0.1.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,303 @@
1
+ """
2
+ ResNet implementation with LoRA support for efficient fine-tuning.
3
+ """
4
+
5
+ import torch
6
+ import torch.nn as nn
7
+ import torch.nn.functional as F
8
+ from typing import Optional, List, Type, Union
9
+ from .lora import LoRALinear, LoRAConfig
10
+
11
+
12
+ class LoRAConv2d(nn.Module):
13
+ """Convolutional layer with LoRA adaptation."""
14
+
15
+ def __init__(self,
16
+ in_channels: int,
17
+ out_channels: int,
18
+ kernel_size: int,
19
+ stride: int = 1,
20
+ padding: int = 0,
21
+ r: int = 4,
22
+ alpha: float = 1.0,
23
+ dropout: float = 0.0):
24
+ super().__init__()
25
+ self.conv = nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding, bias=False)
26
+ self.r = r
27
+ self.alpha = alpha
28
+ self.scaling = alpha / r if r > 0 else 1.0
29
+
30
+ if r > 0:
31
+ # LoRA decomposition for conv layers
32
+ self.lora_A = nn.Parameter(torch.zeros(r, in_channels))
33
+ self.lora_B = nn.Parameter(torch.zeros(out_channels, r))
34
+ self.dropout = nn.Dropout(dropout) if dropout > 0 else nn.Identity()
35
+ self.reset_parameters()
36
+
37
+ def reset_parameters(self):
38
+ if hasattr(self, 'lora_A'):
39
+ nn.init.kaiming_uniform_(self.lora_A, a=math.sqrt(5))
40
+ nn.init.zeros_(self.lora_B)
41
+
42
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
43
+ result = self.conv(x)
44
+
45
+ if self.r > 0 and hasattr(self, 'lora_A'):
46
+ # Apply LoRA adaptation for conv layers
47
+ B, C, H, W = x.shape
48
+ x_reshaped = x.permute(0, 2, 3, 1).reshape(-1, C) # (B*H*W, C)
49
+
50
+ # LoRA forward pass
51
+ lora_out = self.dropout(x_reshaped) @ self.lora_A.T @ self.lora_B.T
52
+ lora_out = lora_out.reshape(B, H, W, -1).permute(0, 3, 1, 2)
53
+
54
+ result = result + lora_out * self.scaling
55
+
56
+ return result
57
+
58
+
59
+ class BasicBlock(nn.Module):
60
+ """Basic ResNet block with LoRA support."""
61
+ expansion = 1
62
+
63
+ def __init__(self,
64
+ inplanes: int,
65
+ planes: int,
66
+ stride: int = 1,
67
+ downsample: Optional[nn.Module] = None,
68
+ lora_config: Optional[LoRAConfig] = None):
69
+ super().__init__()
70
+
71
+ if lora_config and lora_config.r > 0:
72
+ self.conv1 = LoRAConv2d(inplanes, planes, 3, stride, 1,
73
+ r=lora_config.r, alpha=lora_config.alpha, dropout=lora_config.dropout)
74
+ self.conv2 = LoRAConv2d(planes, planes, 3, 1, 1,
75
+ r=lora_config.r, alpha=lora_config.alpha, dropout=lora_config.dropout)
76
+ else:
77
+ self.conv1 = nn.Conv2d(inplanes, planes, 3, stride, 1, bias=False)
78
+ self.conv2 = nn.Conv2d(planes, planes, 3, 1, 1, bias=False)
79
+
80
+ self.bn1 = nn.BatchNorm2d(planes)
81
+ self.bn2 = nn.BatchNorm2d(planes)
82
+ self.relu = nn.ReLU(inplace=True)
83
+ self.downsample = downsample
84
+ self.stride = stride
85
+
86
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
87
+ identity = x
88
+
89
+ out = self.conv1(x)
90
+ out = self.bn1(out)
91
+ out = self.relu(out)
92
+
93
+ out = self.conv2(out)
94
+ out = self.bn2(out)
95
+
96
+ if self.downsample is not None:
97
+ identity = self.downsample(x)
98
+
99
+ out += identity
100
+ out = self.relu(out)
101
+
102
+ return out
103
+
104
+
105
+ class Bottleneck(nn.Module):
106
+ """Bottleneck ResNet block with LoRA support."""
107
+ expansion = 4
108
+
109
+ def __init__(self,
110
+ inplanes: int,
111
+ planes: int,
112
+ stride: int = 1,
113
+ downsample: Optional[nn.Module] = None,
114
+ lora_config: Optional[LoRAConfig] = None):
115
+ super().__init__()
116
+
117
+ if lora_config and lora_config.r > 0:
118
+ self.conv1 = LoRAConv2d(inplanes, planes, 1, 1, 0,
119
+ r=lora_config.r, alpha=lora_config.alpha, dropout=lora_config.dropout)
120
+ self.conv2 = LoRAConv2d(planes, planes, 3, stride, 1,
121
+ r=lora_config.r, alpha=lora_config.alpha, dropout=lora_config.dropout)
122
+ self.conv3 = LoRAConv2d(planes, planes * self.expansion, 1, 1, 0,
123
+ r=lora_config.r, alpha=lora_config.alpha, dropout=lora_config.dropout)
124
+ else:
125
+ self.conv1 = nn.Conv2d(inplanes, planes, 1, bias=False)
126
+ self.conv2 = nn.Conv2d(planes, planes, 3, stride, 1, bias=False)
127
+ self.conv3 = nn.Conv2d(planes, planes * self.expansion, 1, bias=False)
128
+
129
+ self.bn1 = nn.BatchNorm2d(planes)
130
+ self.bn2 = nn.BatchNorm2d(planes)
131
+ self.bn3 = nn.BatchNorm2d(planes * self.expansion)
132
+ self.relu = nn.ReLU(inplace=True)
133
+ self.downsample = downsample
134
+ self.stride = stride
135
+
136
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
137
+ identity = x
138
+
139
+ out = self.conv1(x)
140
+ out = self.bn1(out)
141
+ out = self.relu(out)
142
+
143
+ out = self.conv2(out)
144
+ out = self.bn2(out)
145
+ out = self.relu(out)
146
+
147
+ out = self.conv3(out)
148
+ out = self.bn3(out)
149
+
150
+ if self.downsample is not None:
151
+ identity = self.downsample(x)
152
+
153
+ out += identity
154
+ out = self.relu(out)
155
+
156
+ return out
157
+
158
+
159
+ class ResNet(nn.Module):
160
+ """ResNet architecture with LoRA fine-tuning support."""
161
+
162
+ def __init__(self,
163
+ block: Type[Union[BasicBlock, Bottleneck]],
164
+ layers: List[int],
165
+ num_classes: int = 1000,
166
+ zero_init_residual: bool = False,
167
+ groups: int = 1,
168
+ width_per_group: int = 64,
169
+ replace_stride_with_dilation: Optional[List[bool]] = None,
170
+ norm_layer: Optional[nn.Module] = None,
171
+ lora_config: Optional[LoRAConfig] = None):
172
+ super().__init__()
173
+
174
+ if norm_layer is None:
175
+ norm_layer = nn.BatchNorm2d
176
+ self._norm_layer = norm_layer
177
+ self.lora_config = lora_config
178
+
179
+ self.inplanes = 64
180
+ self.dilation = 1
181
+ if replace_stride_with_dilation is None:
182
+ replace_stride_with_dilation = [False, False, False]
183
+ if len(replace_stride_with_dilation) != 3:
184
+ raise ValueError("replace_stride_with_dilation should be None "
185
+ "or a 3-element tuple, got {}".format(replace_stride_with_dilation))
186
+ self.groups = groups
187
+ self.base_width = width_per_group
188
+
189
+ # Initial convolution
190
+ self.conv1 = nn.Conv2d(3, self.inplanes, kernel_size=7, stride=2, padding=3, bias=False)
191
+ self.bn1 = norm_layer(self.inplanes)
192
+ self.relu = nn.ReLU(inplace=True)
193
+ self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
194
+
195
+ # ResNet layers
196
+ self.layer1 = self._make_layer(block, 64, layers[0])
197
+ self.layer2 = self._make_layer(block, 128, layers[1], stride=2,
198
+ dilate=replace_stride_with_dilation[0])
199
+ self.layer3 = self._make_layer(block, 256, layers[2], stride=2,
200
+ dilate=replace_stride_with_dilation[1])
201
+ self.layer4 = self._make_layer(block, 512, layers[3], stride=2,
202
+ dilate=replace_stride_with_dilation[2])
203
+
204
+ self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
205
+
206
+ # Classification head with LoRA support
207
+ if lora_config and lora_config.r > 0:
208
+ self.fc = LoRALinear(512 * block.expansion, num_classes,
209
+ r=lora_config.r, alpha=lora_config.alpha, dropout=lora_config.dropout)
210
+ else:
211
+ self.fc = nn.Linear(512 * block.expansion, num_classes)
212
+
213
+ # Initialize weights
214
+ for m in self.modules():
215
+ if isinstance(m, nn.Conv2d):
216
+ nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
217
+ elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)):
218
+ nn.init.constant_(m.weight, 1)
219
+ nn.init.constant_(m.bias, 0)
220
+
221
+ # Zero-initialize the last BN in each residual branch
222
+ if zero_init_residual:
223
+ for m in self.modules():
224
+ if isinstance(m, Bottleneck):
225
+ nn.init.constant_(m.bn3.weight, 0)
226
+ elif isinstance(m, BasicBlock):
227
+ nn.init.constant_(m.bn2.weight, 0)
228
+
229
+ def _make_layer(self,
230
+ block: Type[Union[BasicBlock, Bottleneck]],
231
+ planes: int,
232
+ blocks: int,
233
+ stride: int = 1,
234
+ dilate: bool = False) -> nn.Sequential:
235
+ norm_layer = self._norm_layer
236
+ downsample = None
237
+ previous_dilation = self.dilation
238
+
239
+ if dilate:
240
+ self.dilation *= stride
241
+ stride = 1
242
+
243
+ if stride != 1 or self.inplanes != planes * block.expansion:
244
+ downsample = nn.Sequential(
245
+ nn.Conv2d(self.inplanes, planes * block.expansion, 1, stride, bias=False),
246
+ norm_layer(planes * block.expansion),
247
+ )
248
+
249
+ layers = []
250
+ layers.append(block(self.inplanes, planes, stride, downsample,
251
+ groups=self.groups, base_width=self.base_width,
252
+ dilation=previous_dilation, norm_layer=norm_layer,
253
+ lora_config=self.lora_config))
254
+ self.inplanes = planes * block.expansion
255
+
256
+ for _ in range(1, blocks):
257
+ layers.append(block(self.inplanes, planes, groups=self.groups,
258
+ base_width=self.base_width, dilation=self.dilation,
259
+ norm_layer=norm_layer, lora_config=self.lora_config))
260
+
261
+ return nn.Sequential(*layers)
262
+
263
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
264
+ x = self.conv1(x)
265
+ x = self.bn1(x)
266
+ x = self.relu(x)
267
+ x = self.maxpool(x)
268
+
269
+ x = self.layer1(x)
270
+ x = self.layer2(x)
271
+ x = self.layer3(x)
272
+ x = self.layer4(x)
273
+
274
+ x = self.avgpool(x)
275
+ x = torch.flatten(x, 1)
276
+ x = self.fc(x)
277
+
278
+ return x
279
+
280
+
281
+ def resnet18(num_classes: int = 1000, lora_config: Optional[LoRAConfig] = None) -> ResNet:
282
+ """ResNet-18 model with optional LoRA fine-tuning."""
283
+ return ResNet(BasicBlock, [2, 2, 2, 2], num_classes=num_classes, lora_config=lora_config)
284
+
285
+
286
+ def resnet34(num_classes: int = 1000, lora_config: Optional[LoRAConfig] = None) -> ResNet:
287
+ """ResNet-34 model with optional LoRA fine-tuning."""
288
+ return ResNet(BasicBlock, [3, 4, 6, 3], num_classes=num_classes, lora_config=lora_config)
289
+
290
+
291
+ def resnet50(num_classes: int = 1000, lora_config: Optional[LoRAConfig] = None) -> ResNet:
292
+ """ResNet-50 model with optional LoRA fine-tuning."""
293
+ return ResNet(Bottleneck, [3, 4, 6, 3], num_classes=num_classes, lora_config=lora_config)
294
+
295
+
296
+ def resnet101(num_classes: int = 1000, lora_config: Optional[LoRAConfig] = None) -> ResNet:
297
+ """ResNet-101 model with optional LoRA fine-tuning."""
298
+ return ResNet(Bottleneck, [3, 4, 23, 3], num_classes=num_classes, lora_config=lora_config)
299
+
300
+
301
+ def resnet152(num_classes: int = 1000, lora_config: Optional[LoRAConfig] = None) -> ResNet:
302
+ """ResNet-152 model with optional LoRA fine-tuning."""
303
+ return ResNet(Bottleneck, [3, 8, 36, 3], num_classes=num_classes, lora_config=lora_config)