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.
- langvision/__init__.py +77 -2
- langvision/callbacks/base.py +166 -7
- langvision/cli/__init__.py +85 -0
- langvision/cli/complete_cli.py +319 -0
- langvision/cli/config.py +344 -0
- langvision/cli/evaluate.py +201 -0
- langvision/cli/export.py +177 -0
- langvision/cli/finetune.py +165 -48
- langvision/cli/model_zoo.py +162 -0
- langvision/cli/train.py +27 -13
- langvision/cli/utils.py +258 -0
- langvision/components/attention.py +4 -1
- langvision/concepts/__init__.py +9 -0
- langvision/concepts/ccot.py +30 -0
- langvision/concepts/cot.py +29 -0
- langvision/concepts/dpo.py +37 -0
- langvision/concepts/grpo.py +25 -0
- langvision/concepts/lime.py +37 -0
- langvision/concepts/ppo.py +47 -0
- langvision/concepts/rlhf.py +40 -0
- langvision/concepts/rlvr.py +25 -0
- langvision/concepts/shap.py +37 -0
- langvision/data/enhanced_datasets.py +582 -0
- langvision/model_zoo.py +169 -2
- langvision/models/lora.py +189 -17
- langvision/models/multimodal.py +297 -0
- langvision/models/resnet.py +303 -0
- langvision/training/advanced_trainer.py +478 -0
- langvision/training/trainer.py +30 -2
- langvision/utils/config.py +180 -9
- langvision/utils/metrics.py +448 -0
- langvision/utils/setup.py +266 -0
- langvision-0.1.0.dist-info/METADATA +50 -0
- langvision-0.1.0.dist-info/RECORD +61 -0
- {langvision-0.0.1.dist-info → langvision-0.1.0.dist-info}/WHEEL +1 -1
- langvision-0.1.0.dist-info/entry_points.txt +2 -0
- langvision-0.0.1.dist-info/METADATA +0 -463
- langvision-0.0.1.dist-info/RECORD +0 -40
- langvision-0.0.1.dist-info/entry_points.txt +0 -2
- langvision-0.0.1.dist-info/licenses/LICENSE +0 -21
- {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)
|