creyone-layer 1.0.0__tar.gz
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.
- creyone_layer-1.0.0/LICENSE +21 -0
- creyone_layer-1.0.0/PKG-INFO +88 -0
- creyone_layer-1.0.0/README.md +48 -0
- creyone_layer-1.0.0/creyone_layer/__init__.py +7 -0
- creyone_layer-1.0.0/creyone_layer/act.py +93 -0
- creyone_layer-1.0.0/creyone_layer/conv.py +23 -0
- creyone_layer-1.0.0/creyone_layer/norm.py +23 -0
- creyone_layer-1.0.0/creyone_layer/pool.py +29 -0
- creyone_layer-1.0.0/creyone_layer/utils/factory.py +13 -0
- creyone_layer-1.0.0/creyone_layer/utils/registry.py +51 -0
- creyone_layer-1.0.0/creyone_layer/wrap.py +130 -0
- creyone_layer-1.0.0/creyone_layer.egg-info/PKG-INFO +88 -0
- creyone_layer-1.0.0/creyone_layer.egg-info/SOURCES.txt +16 -0
- creyone_layer-1.0.0/creyone_layer.egg-info/dependency_links.txt +1 -0
- creyone_layer-1.0.0/creyone_layer.egg-info/requires.txt +1 -0
- creyone_layer-1.0.0/creyone_layer.egg-info/top_level.txt +1 -0
- creyone_layer-1.0.0/pyproject.toml +33 -0
- creyone_layer-1.0.0/setup.cfg +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 QNiLix
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: creyone_layer
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: PyTorch layer building tools for CREYONE
|
|
5
|
+
Author-email: Linqa Kiriyama <kiriyamalq@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 QNiLix
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://example.com
|
|
29
|
+
Project-URL: Documentation, https://readthedocs.org
|
|
30
|
+
Project-URL: Repository, https://github.com/qnilix/creyone_layer.git
|
|
31
|
+
Project-URL: Bug Tracker, https://github.com/qnilix/creyone_layer/issues
|
|
32
|
+
Project-URL: Changelog, https://github.com/qnilix/creyone_layer/blob/master/CHANGELOG.md
|
|
33
|
+
Classifier: Development Status :: 4 - Beta
|
|
34
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
35
|
+
Requires-Python: >=3.10
|
|
36
|
+
Description-Content-Type: text/markdown
|
|
37
|
+
License-File: LICENSE
|
|
38
|
+
Requires-Dist: torch>=2.0
|
|
39
|
+
Dynamic: license-file
|
|
40
|
+
|
|
41
|
+
# creyone_layer (Beta Package for CreYoNe)
|
|
42
|
+
|
|
43
|
+
Create Your Network (a.k.a. CreYoNe) is a utility tools for making DNN module via torch. This repository provides Layer-sized building blocks for deep learning.
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install creyone-layer
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
From source:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
git clone https://github.com/qaiLN/creyone.git
|
|
55
|
+
cd creyone_layer
|
|
56
|
+
pip install -e .
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Quick Start
|
|
60
|
+
|
|
61
|
+
### Layer registry — `create_layer`
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
from creyone_layer import create_layer
|
|
65
|
+
|
|
66
|
+
relu = create_layer('relu', 'act')(inplace=True)()
|
|
67
|
+
bn = create_layer('batch', 'norm')(dim=2, eps=1e-5, mom=0.1)(64)
|
|
68
|
+
conv = create_layer('base', 'conv')(dim=2, optional='ap')(32, 64, 3)
|
|
69
|
+
pool = create_layer('max', 'pool')(dim=2, optional='ap')(2)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Registered Layers
|
|
73
|
+
|
|
74
|
+
| Family | Names |
|
|
75
|
+
| ------ | ----------------------------------------------------------------------------------- |
|
|
76
|
+
| `conv` | `base`, `depthwise` |
|
|
77
|
+
| `norm` | `batch`, `layer` |
|
|
78
|
+
| `act` | `relu`, `relu6`, `gelu`, `quickgelu`, `sigmoid`, `hardsig`, `hardswish`, `swisheff` |
|
|
79
|
+
| `pool` | `max`, `avg` |
|
|
80
|
+
|
|
81
|
+
### `conv` options (passed via `optional='...'`, `+`-separated)
|
|
82
|
+
|
|
83
|
+
| Flag | Effect |
|
|
84
|
+
| ------ | --------------------------------------------------- |
|
|
85
|
+
| `ap` | auto-pad — output spatial size matches input |
|
|
86
|
+
| `dw` | depthwise — `groups = in_channels` |
|
|
87
|
+
| `grid` | stride = kernel size (grid-like sampling) |
|
|
88
|
+
| `ar` | AutoReshape — accepts `(B, H*W, C)` token sequences |
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# creyone_layer (Beta Package for CreYoNe)
|
|
2
|
+
|
|
3
|
+
Create Your Network (a.k.a. CreYoNe) is a utility tools for making DNN module via torch. This repository provides Layer-sized building blocks for deep learning.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install creyone-layer
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
From source:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
git clone https://github.com/qaiLN/creyone.git
|
|
15
|
+
cd creyone_layer
|
|
16
|
+
pip install -e .
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
### Layer registry — `create_layer`
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
from creyone_layer import create_layer
|
|
25
|
+
|
|
26
|
+
relu = create_layer('relu', 'act')(inplace=True)()
|
|
27
|
+
bn = create_layer('batch', 'norm')(dim=2, eps=1e-5, mom=0.1)(64)
|
|
28
|
+
conv = create_layer('base', 'conv')(dim=2, optional='ap')(32, 64, 3)
|
|
29
|
+
pool = create_layer('max', 'pool')(dim=2, optional='ap')(2)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Registered Layers
|
|
33
|
+
|
|
34
|
+
| Family | Names |
|
|
35
|
+
| ------ | ----------------------------------------------------------------------------------- |
|
|
36
|
+
| `conv` | `base`, `depthwise` |
|
|
37
|
+
| `norm` | `batch`, `layer` |
|
|
38
|
+
| `act` | `relu`, `relu6`, `gelu`, `quickgelu`, `sigmoid`, `hardsig`, `hardswish`, `swisheff` |
|
|
39
|
+
| `pool` | `max`, `avg` |
|
|
40
|
+
|
|
41
|
+
### `conv` options (passed via `optional='...'`, `+`-separated)
|
|
42
|
+
|
|
43
|
+
| Flag | Effect |
|
|
44
|
+
| ------ | --------------------------------------------------- |
|
|
45
|
+
| `ap` | auto-pad — output spatial size matches input |
|
|
46
|
+
| `dw` | depthwise — `groups = in_channels` |
|
|
47
|
+
| `grid` | stride = kernel size (grid-like sampling) |
|
|
48
|
+
| `ar` | AutoReshape — accepts `(B, H*W, C)` token sequences |
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
from functools import partial
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
import torch
|
|
5
|
+
from torch import nn
|
|
6
|
+
|
|
7
|
+
from .utils.registry import register_layer
|
|
8
|
+
|
|
9
|
+
# A memory-efficient implementation of Swish function
|
|
10
|
+
class SwishImplementation(torch.autograd.Function):
|
|
11
|
+
|
|
12
|
+
@staticmethod
|
|
13
|
+
def forward(ctx, i):
|
|
14
|
+
result = i * torch.sigmoid(i)
|
|
15
|
+
ctx.save_for_backward(i)
|
|
16
|
+
return result
|
|
17
|
+
|
|
18
|
+
@staticmethod
|
|
19
|
+
def backward(ctx, grad_output):
|
|
20
|
+
i = ctx.saved_tensors[0]
|
|
21
|
+
sigmoid_i = torch.sigmoid(i)
|
|
22
|
+
return grad_output * (sigmoid_i * (1 + i * (1 - sigmoid_i)))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class MemoryEfficientSwish(nn.Module):
|
|
26
|
+
|
|
27
|
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
|
28
|
+
return SwishImplementation.apply(x)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class QuickGELU(nn.Module):
|
|
32
|
+
|
|
33
|
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
|
34
|
+
return x * torch.sigmoid(1.702 * x)
|
|
35
|
+
|
|
36
|
+
class HardSigmoid(nn.Module):
|
|
37
|
+
|
|
38
|
+
def __init__(self, inplace=True):
|
|
39
|
+
super().__init__()
|
|
40
|
+
self.relu = nn.ReLU6(inplace=inplace)
|
|
41
|
+
|
|
42
|
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
|
43
|
+
return self.relu(x + 3) / 6
|
|
44
|
+
|
|
45
|
+
class HardSwish(nn.Module):
|
|
46
|
+
|
|
47
|
+
def __init__(self, inplace=True):
|
|
48
|
+
super().__init__()
|
|
49
|
+
self.sigmoid = HardSigmoid(inplace=inplace)
|
|
50
|
+
|
|
51
|
+
def forward(self, x):
|
|
52
|
+
return x * self.sigmoid(x)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@register_layer('act')
|
|
56
|
+
def gelu(overwrite: Optional[nn.Module] = None, **kwargs):
|
|
57
|
+
if overwrite is not None: return overwrite
|
|
58
|
+
return nn.GELU
|
|
59
|
+
|
|
60
|
+
@register_layer('act')
|
|
61
|
+
def relu(overwrite: Optional[nn.Module] = None, inplace: bool = False, **kwargs):
|
|
62
|
+
if overwrite is not None: return overwrite
|
|
63
|
+
return partial(nn.ReLU, inplace=inplace)
|
|
64
|
+
|
|
65
|
+
@register_layer('act')
|
|
66
|
+
def relu6(overwrite: Optional[nn.Module] = None, **kwargs):
|
|
67
|
+
if overwrite is not None: return overwrite
|
|
68
|
+
return nn.ReLU6
|
|
69
|
+
|
|
70
|
+
@register_layer('act')
|
|
71
|
+
def sigmoid(overwrite: Optional[nn.Module] = None, **kwargs):
|
|
72
|
+
if overwrite is not None: return overwrite
|
|
73
|
+
return nn.Sigmoid
|
|
74
|
+
|
|
75
|
+
@register_layer('act')
|
|
76
|
+
def hardsig(overwrite: Optional[nn.Module] = None, **kwargs):
|
|
77
|
+
if overwrite is not None: return overwrite
|
|
78
|
+
return HardSigmoid
|
|
79
|
+
|
|
80
|
+
@register_layer('act')
|
|
81
|
+
def hardswish(overwrite: Optional[nn.Module] = None, **kwargs):
|
|
82
|
+
if overwrite is not None: return overwrite
|
|
83
|
+
return HardSwish
|
|
84
|
+
|
|
85
|
+
@register_layer('act')
|
|
86
|
+
def quickgelu(overwrite: Optional[nn.Module] = None, **kwargs):
|
|
87
|
+
if overwrite is not None: return overwrite
|
|
88
|
+
return QuickGELU
|
|
89
|
+
|
|
90
|
+
@register_layer('act')
|
|
91
|
+
def swisheff(overwrite: Optional[nn.Module] = None, **kwargs):
|
|
92
|
+
if overwrite is not None: return overwrite
|
|
93
|
+
return MemoryEfficientSwish
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from torch import nn
|
|
2
|
+
|
|
3
|
+
from .utils.registry import register_layer
|
|
4
|
+
from .wrap import wrap_conv
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def _base(dim: int, opt: set | None = None):
|
|
8
|
+
if opt is None: opt = set()
|
|
9
|
+
if dim == 1: return wrap_conv(nn.Conv1d, opt=opt)
|
|
10
|
+
if dim == 2: return wrap_conv(nn.Conv2d, opt=opt)
|
|
11
|
+
if dim == 3: return wrap_conv(nn.Conv3d, opt=opt)
|
|
12
|
+
raise ValueError(f'Unsupported dim: {dim}')
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@register_layer('conv')
|
|
16
|
+
def base(dim: int = 2, optional: str = '') -> type[nn.Module]:
|
|
17
|
+
return _base(dim, opt=set(optional.split('+')))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@register_layer('conv')
|
|
21
|
+
def depthwise(dim: int = 2, optional: str = '') -> type[nn.Module]:
|
|
22
|
+
seq = set(optional.split('+')); seq.add('dw')
|
|
23
|
+
return _base(dim, opt=seq)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import torch.nn as nn
|
|
2
|
+
|
|
3
|
+
from .utils.registry import register_layer
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def _wrapper(cls, eps: float = 1e-5, **extra_kwargs):
|
|
7
|
+
|
|
8
|
+
def _norm_func(*args, **kwargs):
|
|
9
|
+
_eps = kwargs.pop('eps', eps)
|
|
10
|
+
return cls(*args, eps=_eps, **extra_kwargs, **kwargs)
|
|
11
|
+
|
|
12
|
+
return _norm_func
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@register_layer('norm')
|
|
16
|
+
def layer(eps: float = 1e-5, **_):
|
|
17
|
+
return _wrapper(nn.LayerNorm, eps=eps)
|
|
18
|
+
|
|
19
|
+
@register_layer('norm')
|
|
20
|
+
def batch(eps: float = 1e-5, dim: int = 2, mom: float = 0.1):
|
|
21
|
+
if dim == 1: return _wrapper(nn.BatchNorm1d, eps=eps, momentum=mom)
|
|
22
|
+
if dim == 2: return _wrapper(nn.BatchNorm2d, eps=eps, momentum=mom)
|
|
23
|
+
raise ValueError(f"Unsupported dim={dim} for BatchNorm. Expected 1 or 2.")
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from torch import nn
|
|
2
|
+
|
|
3
|
+
from .utils.registry import register_layer
|
|
4
|
+
from .wrap import wrap_pool
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def _max(dim: int, opt: set | None = None):
|
|
8
|
+
if opt is None: opt = set()
|
|
9
|
+
return wrap_pool(getattr(nn, f"MaxPool{dim}d"), opt=opt)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _avg(dim: int, opt: set | None = None):
|
|
13
|
+
if opt is None: opt = set()
|
|
14
|
+
return wrap_pool(getattr(nn, f"AvgPool{dim}d"), opt=opt)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@register_layer('pool')
|
|
18
|
+
def max(dim: int = 2, optional: str = '') -> callable:
|
|
19
|
+
return _max(dim, opt=set(optional.split('+')))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@register_layer('pool')
|
|
23
|
+
def avg(dim: int = 2, optional: str = '') -> callable:
|
|
24
|
+
return _avg(dim, opt=set(optional.split('+')))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@register_layer('pool')
|
|
28
|
+
def aavg(dim: int = 2, optional: str = '') -> callable:
|
|
29
|
+
return getattr(nn, f"AdaptiveAvgPool{dim}d")
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from typing import Callable, Optional, Union
|
|
2
|
+
from torch import nn
|
|
3
|
+
|
|
4
|
+
from .registry import layer_entrypoint
|
|
5
|
+
|
|
6
|
+
def create_layer(
|
|
7
|
+
layer_name: Optional[Union[str, nn.Module]],
|
|
8
|
+
layer_family: str = 'any',
|
|
9
|
+
otherwise: Callable = lambda *a, **b: nn.Identity()) -> Union[nn.Module, Callable]:
|
|
10
|
+
|
|
11
|
+
if layer_name is None: return otherwise
|
|
12
|
+
if isinstance(layer_name, str): return layer_entrypoint(layer_name, layer_family=layer_family)
|
|
13
|
+
return layer_name
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import sys, warnings
|
|
2
|
+
from collections import defaultdict
|
|
3
|
+
from typing import Any, Callable, Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
_module_to_layers: dict[str, set[str]] = defaultdict(set) # dict of sets to check membership of model in module
|
|
7
|
+
_layer_to_module: dict[str, dict[str, str]] = defaultdict(dict) # mapping of model names to module names
|
|
8
|
+
_layer_entrypoints: dict[str, dict[str, Callable[..., Any]]] = defaultdict(dict) # mapping of model names to architecture entrypoint fns
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def register_layer(layer_family: str = 'any'):
|
|
12
|
+
|
|
13
|
+
def _register_layer(fn: Callable[..., Any]) -> Callable[..., Any]:
|
|
14
|
+
|
|
15
|
+
# lookup containing module
|
|
16
|
+
mod = sys.modules[fn.__module__]
|
|
17
|
+
module_name = fn.__module__.split('.')[-1]
|
|
18
|
+
|
|
19
|
+
# add model to __all__ in module
|
|
20
|
+
layer_name = fn.__name__
|
|
21
|
+
if not hasattr(mod, '__all__'): mod.__all__ = []
|
|
22
|
+
mod.__all__.append(layer_name)
|
|
23
|
+
|
|
24
|
+
# add entries to registry dict/sets
|
|
25
|
+
if layer_name in _layer_entrypoints[layer_family]:
|
|
26
|
+
warnings.warn(
|
|
27
|
+
f'Overwriting {layer_name} in registry with {fn.__module__}.{layer_name}. This is because the name being '
|
|
28
|
+
'registered conflicts with an existing name. Please check if this is not expected.',
|
|
29
|
+
stacklevel=2,
|
|
30
|
+
)
|
|
31
|
+
_layer_entrypoints[layer_family][layer_name] = fn
|
|
32
|
+
_layer_to_module[layer_family][layer_name] = module_name
|
|
33
|
+
_module_to_layers[module_name].add(layer_name)
|
|
34
|
+
|
|
35
|
+
return fn
|
|
36
|
+
|
|
37
|
+
return _register_layer
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def layer_entrypoint(layer_name: str,
|
|
41
|
+
layer_family: Optional[str] = None,
|
|
42
|
+
module_filter: Optional[str] = None) -> Callable[..., Any]:
|
|
43
|
+
"""Fetch a model entrypoint for specified model name
|
|
44
|
+
"""
|
|
45
|
+
if module_filter and layer_name not in _module_to_layers.get(module_filter, set()):
|
|
46
|
+
raise RuntimeError(f'Model ({layer_name}) not found in module {module_filter}.')
|
|
47
|
+
if layer_family is not None and layer_name in _layer_entrypoints[layer_family]:
|
|
48
|
+
return _layer_entrypoints[layer_family][layer_name]
|
|
49
|
+
if layer_name not in _layer_entrypoints['any']:
|
|
50
|
+
raise RuntimeError(f'Layer [{layer_name}] not found in {layer_family} and `any`.')
|
|
51
|
+
return _layer_entrypoints['any'][layer_name]
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
from typing import Optional, Union
|
|
3
|
+
|
|
4
|
+
from torch import nn
|
|
5
|
+
from creyone import cynn
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _consume_args(args: tuple, kwargs: dict) -> tuple[list, dict]:
|
|
9
|
+
"""Normalize positional args to (c1, c2, k), pulling missing values from kwargs.
|
|
10
|
+
|
|
11
|
+
Accepts args in (c1, c2, k) order. Any leading args that are omitted are
|
|
12
|
+
extracted from kwargs using the long-form keys ('in_channels', 'out_channels',
|
|
13
|
+
'kernel_size') or their short aliases ('c1', 'c2', 'k').
|
|
14
|
+
"""
|
|
15
|
+
args = list(args)
|
|
16
|
+
if len(args) == 3: return args, kwargs
|
|
17
|
+
k = kwargs.pop('kernel_size', kwargs.pop('k', None))
|
|
18
|
+
if len(args) == 2: return args + [k], kwargs
|
|
19
|
+
c2 = kwargs.pop('out_channels', kwargs.pop('c2', None))
|
|
20
|
+
if len(args) == 1: return args + [c2, k], kwargs
|
|
21
|
+
c1 = kwargs.pop('in_channels', kwargs.pop('c1', None))
|
|
22
|
+
return [c1, c2, k], kwargs
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _consume_pool_args(args: tuple, kwargs: dict) -> tuple:
|
|
26
|
+
"""Extract kernel size from positional args or kwargs for pool layers."""
|
|
27
|
+
if args:
|
|
28
|
+
return args[0], kwargs
|
|
29
|
+
k = kwargs.pop('kernel_size', kwargs.pop('k', None))
|
|
30
|
+
return k, kwargs
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _compute_same_padding(k: int, d: int = 1) -> Union[int, list[int]]: # kernel, padding, dilation
|
|
34
|
+
"""Pad to 'same' shape outputs."""
|
|
35
|
+
if isinstance(k, int): k = [k]
|
|
36
|
+
if d > 1: k = [d * (x - 1) + 1 for x in k] # actual kernel-size
|
|
37
|
+
p = [x // 2 for x in k] # auto-pad
|
|
38
|
+
return p[0] if len(p) == 1 else p
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _wrapfn(**kwargs):
|
|
42
|
+
"""Extract and return common convolution/pooling parameters from kwargs.
|
|
43
|
+
|
|
44
|
+
Pops 'stride'/'s', 'padding'/'p', 'dilation'/'d', and 'groups'/'g' from
|
|
45
|
+
kwargs, returning them as (s, p, d, g). The remaining kwargs are left for
|
|
46
|
+
the caller to pass through to the underlying layer.
|
|
47
|
+
"""
|
|
48
|
+
s = kwargs.pop('stride', kwargs.pop('s', 1))
|
|
49
|
+
p = kwargs.pop('padding', kwargs.pop('p', 0))
|
|
50
|
+
d = kwargs.pop('dilation', kwargs.pop('d', 1))
|
|
51
|
+
g = kwargs.pop('groups', kwargs.pop('g', 1))
|
|
52
|
+
return s, p, d, g
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class AutoReshape(nn.Module):
|
|
56
|
+
|
|
57
|
+
def __init__(self, mid_layer: nn.Module):
|
|
58
|
+
super().__init__()
|
|
59
|
+
self._inner = mid_layer
|
|
60
|
+
|
|
61
|
+
def forward(self, x: cynn.CreYonT) -> cynn.CreYonT:
|
|
62
|
+
x = x.rearrange('B (H W) C -> B C H W', H=x.H).contiguous()
|
|
63
|
+
return x(self._inner).rearrange('B C H W -> B (H W) C')
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def wrap_conv(cls: nn.Conv2d, opt: Union[set, str, None] = None):
|
|
67
|
+
"""Wrap a Conv Nd class with flexible argument parsing and optional behaviors.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
cls: A ConvNd-compatible class to wrap.
|
|
71
|
+
opt: A '+'-separated string of option flags:
|
|
72
|
+
- 'grid': use the kernel size arg as the stride (grid-like sampling).
|
|
73
|
+
- 'ap': auto-pad so the output spatial size matches the input.
|
|
74
|
+
- 'dw': set groups = in_channels (depthwise convolution).
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
A factory function that accepts (c1, c2, k, ...) positionally or as kwargs
|
|
78
|
+
and forwards them to ``cls`` with stride, padding, dilation, and groups set.
|
|
79
|
+
"""
|
|
80
|
+
if opt is None: opt = set()
|
|
81
|
+
elif isinstance(opt, str): opt = set(opt.split('+'))
|
|
82
|
+
|
|
83
|
+
def _fn(*args, **kwargs):
|
|
84
|
+
args, kwargs = _consume_args(args, kwargs)
|
|
85
|
+
s, p, d, g = _wrapfn(**kwargs)
|
|
86
|
+
if 'grid' in opt: s = args[-1]
|
|
87
|
+
if 'ap' in opt: p = _compute_same_padding(args[-1], d)
|
|
88
|
+
if 'dw' in opt: g = args[0]
|
|
89
|
+
|
|
90
|
+
ins = cls(*args, stride=s, padding=p, dilation=d, groups=g, **kwargs)
|
|
91
|
+
if 'ar' in opt: ins = AutoReshape(ins)
|
|
92
|
+
return ins
|
|
93
|
+
|
|
94
|
+
return _fn
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def wrap_pool(cls, opt: Union[set, str, None] = None):
|
|
98
|
+
"""Wrap a pooling class with flexible argument parsing and optional behaviors.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
cls: A PoolNd-compatible class to wrap. Dilation is forwarded automatically
|
|
102
|
+
only when the class supports it (MaxPoolNd does, AvgPoolNd does not).
|
|
103
|
+
opt: A '+'-separated string of option flags:
|
|
104
|
+
- 'grid': use the kernel size arg as the stride (grid-like sampling).
|
|
105
|
+
- 'ap': auto-pad so the output spatial size matches the input.
|
|
106
|
+
- 'ar': wrap output in AutoReshape for (B HW C) tensors.
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
A factory function that accepts (k, ...) positionally or as kwargs
|
|
110
|
+
and forwards them to ``cls`` with stride, padding, and dilation set.
|
|
111
|
+
"""
|
|
112
|
+
if opt is None: opt = set()
|
|
113
|
+
elif isinstance(opt, str): opt = set(opt.split('+'))
|
|
114
|
+
_has_dilation = 'dilation' in inspect.signature(cls).parameters
|
|
115
|
+
|
|
116
|
+
def _fn(*args, **kwargs):
|
|
117
|
+
k, kwargs = _consume_pool_args(args, kwargs)
|
|
118
|
+
s, p, d, _ = _wrapfn(**kwargs)
|
|
119
|
+
if 'grid' in opt: s = k
|
|
120
|
+
if 'ap' in opt: p = _compute_same_padding(k, d if _has_dilation else 1)
|
|
121
|
+
|
|
122
|
+
extra = {'dilation': d} if _has_dilation else {}
|
|
123
|
+
ins = cls(k, stride=s, padding=p, **extra, **kwargs)
|
|
124
|
+
if 'ar' in opt: ins = AutoReshape(ins)
|
|
125
|
+
return ins
|
|
126
|
+
|
|
127
|
+
return _fn
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: creyone_layer
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: PyTorch layer building tools for CREYONE
|
|
5
|
+
Author-email: Linqa Kiriyama <kiriyamalq@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 QNiLix
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://example.com
|
|
29
|
+
Project-URL: Documentation, https://readthedocs.org
|
|
30
|
+
Project-URL: Repository, https://github.com/qnilix/creyone_layer.git
|
|
31
|
+
Project-URL: Bug Tracker, https://github.com/qnilix/creyone_layer/issues
|
|
32
|
+
Project-URL: Changelog, https://github.com/qnilix/creyone_layer/blob/master/CHANGELOG.md
|
|
33
|
+
Classifier: Development Status :: 4 - Beta
|
|
34
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
35
|
+
Requires-Python: >=3.10
|
|
36
|
+
Description-Content-Type: text/markdown
|
|
37
|
+
License-File: LICENSE
|
|
38
|
+
Requires-Dist: torch>=2.0
|
|
39
|
+
Dynamic: license-file
|
|
40
|
+
|
|
41
|
+
# creyone_layer (Beta Package for CreYoNe)
|
|
42
|
+
|
|
43
|
+
Create Your Network (a.k.a. CreYoNe) is a utility tools for making DNN module via torch. This repository provides Layer-sized building blocks for deep learning.
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install creyone-layer
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
From source:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
git clone https://github.com/qaiLN/creyone.git
|
|
55
|
+
cd creyone_layer
|
|
56
|
+
pip install -e .
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Quick Start
|
|
60
|
+
|
|
61
|
+
### Layer registry — `create_layer`
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
from creyone_layer import create_layer
|
|
65
|
+
|
|
66
|
+
relu = create_layer('relu', 'act')(inplace=True)()
|
|
67
|
+
bn = create_layer('batch', 'norm')(dim=2, eps=1e-5, mom=0.1)(64)
|
|
68
|
+
conv = create_layer('base', 'conv')(dim=2, optional='ap')(32, 64, 3)
|
|
69
|
+
pool = create_layer('max', 'pool')(dim=2, optional='ap')(2)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Registered Layers
|
|
73
|
+
|
|
74
|
+
| Family | Names |
|
|
75
|
+
| ------ | ----------------------------------------------------------------------------------- |
|
|
76
|
+
| `conv` | `base`, `depthwise` |
|
|
77
|
+
| `norm` | `batch`, `layer` |
|
|
78
|
+
| `act` | `relu`, `relu6`, `gelu`, `quickgelu`, `sigmoid`, `hardsig`, `hardswish`, `swisheff` |
|
|
79
|
+
| `pool` | `max`, `avg` |
|
|
80
|
+
|
|
81
|
+
### `conv` options (passed via `optional='...'`, `+`-separated)
|
|
82
|
+
|
|
83
|
+
| Flag | Effect |
|
|
84
|
+
| ------ | --------------------------------------------------- |
|
|
85
|
+
| `ap` | auto-pad — output spatial size matches input |
|
|
86
|
+
| `dw` | depthwise — `groups = in_channels` |
|
|
87
|
+
| `grid` | stride = kernel size (grid-like sampling) |
|
|
88
|
+
| `ar` | AutoReshape — accepts `(B, H*W, C)` token sequences |
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
creyone_layer/__init__.py
|
|
5
|
+
creyone_layer/act.py
|
|
6
|
+
creyone_layer/conv.py
|
|
7
|
+
creyone_layer/norm.py
|
|
8
|
+
creyone_layer/pool.py
|
|
9
|
+
creyone_layer/wrap.py
|
|
10
|
+
creyone_layer.egg-info/PKG-INFO
|
|
11
|
+
creyone_layer.egg-info/SOURCES.txt
|
|
12
|
+
creyone_layer.egg-info/dependency_links.txt
|
|
13
|
+
creyone_layer.egg-info/requires.txt
|
|
14
|
+
creyone_layer.egg-info/top_level.txt
|
|
15
|
+
creyone_layer/utils/factory.py
|
|
16
|
+
creyone_layer/utils/registry.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
torch>=2.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
creyone_layer
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "creyone_layer"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
dependencies = [
|
|
9
|
+
"torch>=2.0"
|
|
10
|
+
]
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Linqa Kiriyama", email = "kiriyamalq@gmail.com"},
|
|
14
|
+
]
|
|
15
|
+
description = "PyTorch layer building tools for CREYONE"
|
|
16
|
+
readme = "README.md"
|
|
17
|
+
license = {file = "LICENSE"}
|
|
18
|
+
keywords = []
|
|
19
|
+
classifiers = [
|
|
20
|
+
"Development Status :: 4 - Beta",
|
|
21
|
+
"Programming Language :: Python :: 3 :: Only"
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[project.urls]
|
|
25
|
+
Homepage = "https://example.com"
|
|
26
|
+
Documentation = "https://readthedocs.org"
|
|
27
|
+
Repository = "https://github.com/qnilix/creyone_layer.git"
|
|
28
|
+
"Bug Tracker" = "https://github.com/qnilix/creyone_layer/issues"
|
|
29
|
+
Changelog = "https://github.com/qnilix/creyone_layer/blob/master/CHANGELOG.md"
|
|
30
|
+
|
|
31
|
+
[tool.setuptools.packages.find]
|
|
32
|
+
where = ["."]
|
|
33
|
+
include = ["creyone_layer*"]
|