ilovetools 0.2.18__tar.gz → 0.2.19__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.
Files changed (78) hide show
  1. {ilovetools-0.2.18/ilovetools.egg-info → ilovetools-0.2.19}/PKG-INFO +2 -2
  2. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/__init__.py +2 -2
  3. ilovetools-0.2.19/ilovetools/ml/cnn.py +619 -0
  4. {ilovetools-0.2.18 → ilovetools-0.2.19/ilovetools.egg-info}/PKG-INFO +2 -2
  5. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools.egg-info/SOURCES.txt +2 -0
  6. {ilovetools-0.2.18 → ilovetools-0.2.19}/pyproject.toml +2 -2
  7. {ilovetools-0.2.18 → ilovetools-0.2.19}/setup.py +2 -2
  8. ilovetools-0.2.19/tests/test_cnn.py +394 -0
  9. {ilovetools-0.2.18 → ilovetools-0.2.19}/LICENSE +0 -0
  10. {ilovetools-0.2.18 → ilovetools-0.2.19}/MANIFEST.in +0 -0
  11. {ilovetools-0.2.18 → ilovetools-0.2.19}/README.md +0 -0
  12. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ai/__init__.py +0 -0
  13. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ai/embeddings.py +0 -0
  14. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ai/inference.py +0 -0
  15. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ai/llm_helpers.py +0 -0
  16. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/audio/__init__.py +0 -0
  17. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/automation/__init__.py +0 -0
  18. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/automation/file_organizer.py +0 -0
  19. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/conversion/__init__.py +0 -0
  20. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/conversion/config_converter.py +0 -0
  21. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/conversion/config_converter_fixed_header.py +0 -0
  22. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/data/__init__.py +0 -0
  23. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/data/feature_engineering.py +0 -0
  24. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/data/preprocessing.py +0 -0
  25. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/database/__init__.py +0 -0
  26. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/datetime/__init__.py +0 -0
  27. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/email/__init__.py +0 -0
  28. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/email/template_engine.py +0 -0
  29. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/files/__init__.py +0 -0
  30. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/image/__init__.py +0 -0
  31. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ml/__init__.py +0 -0
  32. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ml/activations.py +0 -0
  33. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ml/anomaly_detection.py +0 -0
  34. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ml/attention.py +0 -0
  35. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ml/clustering.py +0 -0
  36. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ml/cross_validation.py +0 -0
  37. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ml/dimensionality.py +0 -0
  38. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ml/ensemble.py +0 -0
  39. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ml/feature_selection.py +0 -0
  40. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ml/gradient_descent.py +0 -0
  41. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ml/imbalanced.py +0 -0
  42. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ml/interpretation.py +0 -0
  43. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ml/loss_functions.py +0 -0
  44. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ml/metrics.py +0 -0
  45. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ml/neural_network.py +0 -0
  46. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ml/normalization.py +0 -0
  47. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ml/optimizers.py +0 -0
  48. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ml/pipeline.py +0 -0
  49. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ml/regularization.py +0 -0
  50. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ml/timeseries.py +0 -0
  51. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/ml/tuning.py +0 -0
  52. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/security/__init__.py +0 -0
  53. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/security/password_checker.py +0 -0
  54. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/text/__init__.py +0 -0
  55. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/utils/__init__.py +0 -0
  56. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/utils/cache_system.py +0 -0
  57. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/utils/logger.py +0 -0
  58. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/utils/rate_limiter.py +0 -0
  59. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/utils/retry.py +0 -0
  60. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/validation/__init__.py +0 -0
  61. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/validation/data_validator.py +0 -0
  62. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/web/__init__.py +0 -0
  63. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/web/scraper.py +0 -0
  64. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools/web/url_shortener.py +0 -0
  65. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools.egg-info/dependency_links.txt +0 -0
  66. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools.egg-info/requires.txt +0 -0
  67. {ilovetools-0.2.18 → ilovetools-0.2.19}/ilovetools.egg-info/top_level.txt +0 -0
  68. {ilovetools-0.2.18 → ilovetools-0.2.19}/requirements.txt +0 -0
  69. {ilovetools-0.2.18 → ilovetools-0.2.19}/setup.cfg +0 -0
  70. {ilovetools-0.2.18 → ilovetools-0.2.19}/tests/__init__.py +0 -0
  71. {ilovetools-0.2.18 → ilovetools-0.2.19}/tests/test_activations.py +0 -0
  72. {ilovetools-0.2.18 → ilovetools-0.2.19}/tests/test_attention.py +0 -0
  73. {ilovetools-0.2.18 → ilovetools-0.2.19}/tests/test_gradient_descent.py +0 -0
  74. {ilovetools-0.2.18 → ilovetools-0.2.19}/tests/test_loss_functions.py +0 -0
  75. {ilovetools-0.2.18 → ilovetools-0.2.19}/tests/test_neural_network.py +0 -0
  76. {ilovetools-0.2.18 → ilovetools-0.2.19}/tests/test_normalization.py +0 -0
  77. {ilovetools-0.2.18 → ilovetools-0.2.19}/tests/test_optimizers.py +0 -0
  78. {ilovetools-0.2.18 → ilovetools-0.2.19}/tests/test_regularization.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ilovetools
3
- Version: 0.2.18
3
+ Version: 0.2.19
4
4
  Summary: A comprehensive Python utility library with modular tools for AI/ML, data processing, and daily programming needs
5
5
  Home-page: https://github.com/AliMehdi512/ilovetools
6
6
  Author: Ali Mehdi
@@ -11,7 +11,7 @@ Project-URL: Repository, https://github.com/AliMehdi512/ilovetools
11
11
  Project-URL: Issues, https://github.com/AliMehdi512/ilovetools/issues
12
12
  Project-URL: Bug Reports, https://github.com/AliMehdi512/ilovetools/issues
13
13
  Project-URL: Source, https://github.com/AliMehdi512/ilovetools
14
- Keywords: utilities,tools,ai,ml,data-processing,automation,attention-mechanism,self-attention,multi-head-attention,transformers,bert,gpt,positional-encoding
14
+ Keywords: utilities,tools,ai,ml,data-processing,automation,cnn,convolutional-neural-networks,conv2d,pooling,computer-vision,image-processing
15
15
  Classifier: Development Status :: 3 - Alpha
16
16
  Classifier: Intended Audience :: Developers
17
17
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
@@ -2,8 +2,8 @@
2
2
  ilovetools - A comprehensive Python utility library
3
3
  """
4
4
 
5
- __version__ = "0.2.17"
6
- # release marker: 0.2.17
5
+ __version__ = "0.2.18"
6
+ # release marker: 0.2.18
7
7
  __author__ = "Ali Mehdi"
8
8
  __email__ = "ali.mehdi.dev579@gmail.com"
9
9
 
@@ -0,0 +1,619 @@
1
+ """
2
+ Convolutional Neural Network Operations
3
+
4
+ This module provides core CNN operations:
5
+ - 2D Convolution (Conv2D)
6
+ - Pooling Operations (Max, Average, Global)
7
+ - Padding Strategies (Same, Valid, Custom)
8
+ - Im2Col and Col2Im transformations
9
+ - Depthwise and Separable Convolutions
10
+ - Dilated Convolutions
11
+
12
+ All operations support batched inputs and are optimized for performance.
13
+ """
14
+
15
+ import numpy as np
16
+ from typing import Tuple, Union, Optional
17
+
18
+
19
+ # ============================================================================
20
+ # 2D CONVOLUTION
21
+ # ============================================================================
22
+
23
+ def conv2d(
24
+ input: np.ndarray,
25
+ kernel: np.ndarray,
26
+ stride: Union[int, Tuple[int, int]] = 1,
27
+ padding: Union[str, int, Tuple[int, int]] = 0,
28
+ dilation: Union[int, Tuple[int, int]] = 1
29
+ ) -> np.ndarray:
30
+ """
31
+ 2D Convolution Operation
32
+
33
+ Applies a 2D convolution over an input signal composed of several input planes.
34
+
35
+ Args:
36
+ input: Input tensor of shape (batch, in_channels, height, width)
37
+ kernel: Kernel tensor of shape (out_channels, in_channels, kernel_h, kernel_w)
38
+ stride: Stride of the convolution (default: 1)
39
+ padding: Padding added to input ('same', 'valid', or int/tuple)
40
+ dilation: Spacing between kernel elements (default: 1)
41
+
42
+ Returns:
43
+ Output tensor of shape (batch, out_channels, out_height, out_width)
44
+
45
+ Example:
46
+ >>> # Single channel convolution
47
+ >>> input = np.random.randn(1, 1, 28, 28) # (batch, channels, H, W)
48
+ >>> kernel = np.random.randn(32, 1, 3, 3) # (out_ch, in_ch, kH, kW)
49
+ >>> output = conv2d(input, kernel, stride=1, padding='same')
50
+ >>> print(output.shape) # (1, 32, 28, 28)
51
+
52
+ >>> # RGB image convolution
53
+ >>> input = np.random.randn(8, 3, 224, 224) # RGB images
54
+ >>> kernel = np.random.randn(64, 3, 3, 3) # 64 filters
55
+ >>> output = conv2d(input, kernel, stride=2, padding=1)
56
+ >>> print(output.shape) # (8, 64, 112, 112)
57
+ """
58
+ # Parse stride
59
+ if isinstance(stride, int):
60
+ stride_h, stride_w = stride, stride
61
+ else:
62
+ stride_h, stride_w = stride
63
+
64
+ # Parse dilation
65
+ if isinstance(dilation, int):
66
+ dilation_h, dilation_w = dilation, dilation
67
+ else:
68
+ dilation_h, dilation_w = dilation
69
+
70
+ # Get dimensions
71
+ batch_size, in_channels, in_h, in_w = input.shape
72
+ out_channels, _, kernel_h, kernel_w = kernel.shape
73
+
74
+ # Apply padding
75
+ if isinstance(padding, str):
76
+ if padding == 'same':
77
+ # Calculate padding for 'same' output size
78
+ pad_h = ((in_h - 1) * stride_h + dilation_h * (kernel_h - 1) + 1 - in_h) // 2
79
+ pad_w = ((in_w - 1) * stride_w + dilation_w * (kernel_w - 1) + 1 - in_w) // 2
80
+ pad_h, pad_w = max(0, pad_h), max(0, pad_w)
81
+ elif padding == 'valid':
82
+ pad_h, pad_w = 0, 0
83
+ else:
84
+ raise ValueError(f"Unknown padding mode: {padding}")
85
+ elif isinstance(padding, int):
86
+ pad_h, pad_w = padding, padding
87
+ else:
88
+ pad_h, pad_w = padding
89
+
90
+ # Pad input
91
+ if pad_h > 0 or pad_w > 0:
92
+ input = np.pad(input, ((0, 0), (0, 0), (pad_h, pad_h), (pad_w, pad_w)), mode='constant')
93
+ in_h, in_w = input.shape[2], input.shape[3]
94
+
95
+ # Calculate output dimensions
96
+ out_h = (in_h - dilation_h * (kernel_h - 1) - 1) // stride_h + 1
97
+ out_w = (in_w - dilation_w * (kernel_w - 1) - 1) // stride_w + 1
98
+
99
+ # Initialize output
100
+ output = np.zeros((batch_size, out_channels, out_h, out_w))
101
+
102
+ # Perform convolution
103
+ for b in range(batch_size):
104
+ for oc in range(out_channels):
105
+ for i in range(out_h):
106
+ for j in range(out_w):
107
+ # Calculate input region
108
+ h_start = i * stride_h
109
+ w_start = j * stride_w
110
+
111
+ # Extract region with dilation
112
+ region = input[b, :,
113
+ h_start:h_start + dilation_h * kernel_h:dilation_h,
114
+ w_start:w_start + dilation_w * kernel_w:dilation_w]
115
+
116
+ # Convolve
117
+ output[b, oc, i, j] = np.sum(region * kernel[oc])
118
+
119
+ return output
120
+
121
+
122
+ def conv2d_fast(
123
+ input: np.ndarray,
124
+ kernel: np.ndarray,
125
+ stride: Union[int, Tuple[int, int]] = 1,
126
+ padding: Union[str, int, Tuple[int, int]] = 0
127
+ ) -> np.ndarray:
128
+ """
129
+ Fast 2D Convolution using im2col
130
+
131
+ More efficient implementation using matrix multiplication.
132
+
133
+ Args:
134
+ input: Input tensor of shape (batch, in_channels, height, width)
135
+ kernel: Kernel tensor of shape (out_channels, in_channels, kernel_h, kernel_w)
136
+ stride: Stride of the convolution
137
+ padding: Padding added to input
138
+
139
+ Returns:
140
+ Output tensor of shape (batch, out_channels, out_height, out_width)
141
+
142
+ Example:
143
+ >>> input = np.random.randn(8, 3, 224, 224)
144
+ >>> kernel = np.random.randn(64, 3, 3, 3)
145
+ >>> output = conv2d_fast(input, kernel, stride=1, padding='same')
146
+ >>> print(output.shape) # (8, 64, 224, 224)
147
+ """
148
+ # Parse stride
149
+ if isinstance(stride, int):
150
+ stride_h, stride_w = stride, stride
151
+ else:
152
+ stride_h, stride_w = stride
153
+
154
+ # Get dimensions
155
+ batch_size, in_channels, in_h, in_w = input.shape
156
+ out_channels, _, kernel_h, kernel_w = kernel.shape
157
+
158
+ # Apply padding
159
+ if isinstance(padding, str):
160
+ if padding == 'same':
161
+ pad_h = ((in_h - 1) * stride_h + kernel_h - in_h) // 2
162
+ pad_w = ((in_w - 1) * stride_w + kernel_w - in_w) // 2
163
+ pad_h, pad_w = max(0, pad_h), max(0, pad_w)
164
+ elif padding == 'valid':
165
+ pad_h, pad_w = 0, 0
166
+ elif isinstance(padding, int):
167
+ pad_h, pad_w = padding, padding
168
+ else:
169
+ pad_h, pad_w = padding
170
+
171
+ # Pad input
172
+ if pad_h > 0 or pad_w > 0:
173
+ input = np.pad(input, ((0, 0), (0, 0), (pad_h, pad_h), (pad_w, pad_w)), mode='constant')
174
+ in_h, in_w = input.shape[2], input.shape[3]
175
+
176
+ # Calculate output dimensions
177
+ out_h = (in_h - kernel_h) // stride_h + 1
178
+ out_w = (in_w - kernel_w) // stride_w + 1
179
+
180
+ # Im2col transformation
181
+ col = im2col(input, kernel_h, kernel_w, stride_h, stride_w)
182
+
183
+ # Reshape kernel
184
+ kernel_col = kernel.reshape(out_channels, -1)
185
+
186
+ # Matrix multiplication
187
+ output = np.dot(kernel_col, col)
188
+
189
+ # Reshape output
190
+ output = output.reshape(out_channels, out_h, out_w, batch_size)
191
+ output = output.transpose(3, 0, 1, 2)
192
+
193
+ return output
194
+
195
+
196
+ # ============================================================================
197
+ # POOLING OPERATIONS
198
+ # ============================================================================
199
+
200
+ def max_pool2d(
201
+ input: np.ndarray,
202
+ pool_size: Union[int, Tuple[int, int]] = 2,
203
+ stride: Optional[Union[int, Tuple[int, int]]] = None,
204
+ padding: Union[int, Tuple[int, int]] = 0
205
+ ) -> np.ndarray:
206
+ """
207
+ 2D Max Pooling
208
+
209
+ Applies a 2D max pooling over an input signal.
210
+
211
+ Args:
212
+ input: Input tensor of shape (batch, channels, height, width)
213
+ pool_size: Size of the pooling window (default: 2)
214
+ stride: Stride of the pooling (default: same as pool_size)
215
+ padding: Padding added to input (default: 0)
216
+
217
+ Returns:
218
+ Output tensor after max pooling
219
+
220
+ Example:
221
+ >>> input = np.random.randn(8, 64, 28, 28)
222
+ >>> output = max_pool2d(input, pool_size=2, stride=2)
223
+ >>> print(output.shape) # (8, 64, 14, 14)
224
+ """
225
+ # Parse pool_size
226
+ if isinstance(pool_size, int):
227
+ pool_h, pool_w = pool_size, pool_size
228
+ else:
229
+ pool_h, pool_w = pool_size
230
+
231
+ # Parse stride (default to pool_size)
232
+ if stride is None:
233
+ stride_h, stride_w = pool_h, pool_w
234
+ elif isinstance(stride, int):
235
+ stride_h, stride_w = stride, stride
236
+ else:
237
+ stride_h, stride_w = stride
238
+
239
+ # Parse padding
240
+ if isinstance(padding, int):
241
+ pad_h, pad_w = padding, padding
242
+ else:
243
+ pad_h, pad_w = padding
244
+
245
+ # Get dimensions
246
+ batch_size, channels, in_h, in_w = input.shape
247
+
248
+ # Apply padding
249
+ if pad_h > 0 or pad_w > 0:
250
+ input = np.pad(input, ((0, 0), (0, 0), (pad_h, pad_h), (pad_w, pad_w)),
251
+ mode='constant', constant_values=-np.inf)
252
+ in_h, in_w = input.shape[2], input.shape[3]
253
+
254
+ # Calculate output dimensions
255
+ out_h = (in_h - pool_h) // stride_h + 1
256
+ out_w = (in_w - pool_w) // stride_w + 1
257
+
258
+ # Initialize output
259
+ output = np.zeros((batch_size, channels, out_h, out_w))
260
+
261
+ # Perform max pooling
262
+ for b in range(batch_size):
263
+ for c in range(channels):
264
+ for i in range(out_h):
265
+ for j in range(out_w):
266
+ h_start = i * stride_h
267
+ w_start = j * stride_w
268
+
269
+ # Extract region
270
+ region = input[b, c, h_start:h_start + pool_h, w_start:w_start + pool_w]
271
+
272
+ # Take maximum
273
+ output[b, c, i, j] = np.max(region)
274
+
275
+ return output
276
+
277
+
278
+ def avg_pool2d(
279
+ input: np.ndarray,
280
+ pool_size: Union[int, Tuple[int, int]] = 2,
281
+ stride: Optional[Union[int, Tuple[int, int]]] = None,
282
+ padding: Union[int, Tuple[int, int]] = 0
283
+ ) -> np.ndarray:
284
+ """
285
+ 2D Average Pooling
286
+
287
+ Applies a 2D average pooling over an input signal.
288
+
289
+ Args:
290
+ input: Input tensor of shape (batch, channels, height, width)
291
+ pool_size: Size of the pooling window (default: 2)
292
+ stride: Stride of the pooling (default: same as pool_size)
293
+ padding: Padding added to input (default: 0)
294
+
295
+ Returns:
296
+ Output tensor after average pooling
297
+
298
+ Example:
299
+ >>> input = np.random.randn(8, 64, 28, 28)
300
+ >>> output = avg_pool2d(input, pool_size=2, stride=2)
301
+ >>> print(output.shape) # (8, 64, 14, 14)
302
+ """
303
+ # Parse pool_size
304
+ if isinstance(pool_size, int):
305
+ pool_h, pool_w = pool_size, pool_size
306
+ else:
307
+ pool_h, pool_w = pool_size
308
+
309
+ # Parse stride
310
+ if stride is None:
311
+ stride_h, stride_w = pool_h, pool_w
312
+ elif isinstance(stride, int):
313
+ stride_h, stride_w = stride, stride
314
+ else:
315
+ stride_h, stride_w = stride
316
+
317
+ # Parse padding
318
+ if isinstance(padding, int):
319
+ pad_h, pad_w = padding, padding
320
+ else:
321
+ pad_h, pad_w = padding
322
+
323
+ # Get dimensions
324
+ batch_size, channels, in_h, in_w = input.shape
325
+
326
+ # Apply padding
327
+ if pad_h > 0 or pad_w > 0:
328
+ input = np.pad(input, ((0, 0), (0, 0), (pad_h, pad_h), (pad_w, pad_w)), mode='constant')
329
+ in_h, in_w = input.shape[2], input.shape[3]
330
+
331
+ # Calculate output dimensions
332
+ out_h = (in_h - pool_h) // stride_h + 1
333
+ out_w = (in_w - pool_w) // stride_w + 1
334
+
335
+ # Initialize output
336
+ output = np.zeros((batch_size, channels, out_h, out_w))
337
+
338
+ # Perform average pooling
339
+ for b in range(batch_size):
340
+ for c in range(channels):
341
+ for i in range(out_h):
342
+ for j in range(out_w):
343
+ h_start = i * stride_h
344
+ w_start = j * stride_w
345
+
346
+ # Extract region
347
+ region = input[b, c, h_start:h_start + pool_h, w_start:w_start + pool_w]
348
+
349
+ # Take average
350
+ output[b, c, i, j] = np.mean(region)
351
+
352
+ return output
353
+
354
+
355
+ def global_avg_pool2d(input: np.ndarray) -> np.ndarray:
356
+ """
357
+ Global Average Pooling
358
+
359
+ Averages each feature map to a single value.
360
+
361
+ Args:
362
+ input: Input tensor of shape (batch, channels, height, width)
363
+
364
+ Returns:
365
+ Output tensor of shape (batch, channels, 1, 1)
366
+
367
+ Example:
368
+ >>> input = np.random.randn(8, 512, 7, 7)
369
+ >>> output = global_avg_pool2d(input)
370
+ >>> print(output.shape) # (8, 512, 1, 1)
371
+ """
372
+ return np.mean(input, axis=(2, 3), keepdims=True)
373
+
374
+
375
+ def global_max_pool2d(input: np.ndarray) -> np.ndarray:
376
+ """
377
+ Global Max Pooling
378
+
379
+ Takes maximum of each feature map.
380
+
381
+ Args:
382
+ input: Input tensor of shape (batch, channels, height, width)
383
+
384
+ Returns:
385
+ Output tensor of shape (batch, channels, 1, 1)
386
+
387
+ Example:
388
+ >>> input = np.random.randn(8, 512, 7, 7)
389
+ >>> output = global_max_pool2d(input)
390
+ >>> print(output.shape) # (8, 512, 1, 1)
391
+ """
392
+ return np.max(input, axis=(2, 3), keepdims=True)
393
+
394
+
395
+ # ============================================================================
396
+ # IM2COL TRANSFORMATION
397
+ # ============================================================================
398
+
399
+ def im2col(
400
+ input: np.ndarray,
401
+ kernel_h: int,
402
+ kernel_w: int,
403
+ stride_h: int = 1,
404
+ stride_w: int = 1
405
+ ) -> np.ndarray:
406
+ """
407
+ Im2Col transformation for efficient convolution
408
+
409
+ Transforms image into column matrix for matrix multiplication.
410
+
411
+ Args:
412
+ input: Input tensor of shape (batch, channels, height, width)
413
+ kernel_h: Kernel height
414
+ kernel_w: Kernel width
415
+ stride_h: Vertical stride
416
+ stride_w: Horizontal stride
417
+
418
+ Returns:
419
+ Column matrix of shape (kernel_h * kernel_w * channels, out_h * out_w * batch)
420
+
421
+ Example:
422
+ >>> input = np.random.randn(8, 3, 32, 32)
423
+ >>> col = im2col(input, kernel_h=3, kernel_w=3, stride_h=1, stride_w=1)
424
+ >>> print(col.shape) # (27, 7200)
425
+ """
426
+ batch_size, channels, in_h, in_w = input.shape
427
+
428
+ # Calculate output dimensions
429
+ out_h = (in_h - kernel_h) // stride_h + 1
430
+ out_w = (in_w - kernel_w) // stride_w + 1
431
+
432
+ # Initialize column matrix
433
+ col = np.zeros((batch_size, channels, kernel_h, kernel_w, out_h, out_w))
434
+
435
+ # Fill column matrix
436
+ for i in range(kernel_h):
437
+ i_max = i + stride_h * out_h
438
+ for j in range(kernel_w):
439
+ j_max = j + stride_w * out_w
440
+ col[:, :, i, j, :, :] = input[:, :, i:i_max:stride_h, j:j_max:stride_w]
441
+
442
+ # Reshape
443
+ col = col.transpose(0, 4, 5, 1, 2, 3).reshape(batch_size * out_h * out_w, -1)
444
+
445
+ return col.T
446
+
447
+
448
+ def col2im(
449
+ col: np.ndarray,
450
+ input_shape: Tuple[int, int, int, int],
451
+ kernel_h: int,
452
+ kernel_w: int,
453
+ stride_h: int = 1,
454
+ stride_w: int = 1
455
+ ) -> np.ndarray:
456
+ """
457
+ Col2Im transformation (inverse of im2col)
458
+
459
+ Transforms column matrix back to image format.
460
+
461
+ Args:
462
+ col: Column matrix
463
+ input_shape: Original input shape (batch, channels, height, width)
464
+ kernel_h: Kernel height
465
+ kernel_w: Kernel width
466
+ stride_h: Vertical stride
467
+ stride_w: Horizontal stride
468
+
469
+ Returns:
470
+ Image tensor of shape input_shape
471
+
472
+ Example:
473
+ >>> col = np.random.randn(27, 7200)
474
+ >>> img = col2im(col, (8, 3, 32, 32), kernel_h=3, kernel_w=3)
475
+ >>> print(img.shape) # (8, 3, 32, 32)
476
+ """
477
+ batch_size, channels, in_h, in_w = input_shape
478
+
479
+ # Calculate output dimensions
480
+ out_h = (in_h - kernel_h) // stride_h + 1
481
+ out_w = (in_w - kernel_w) // stride_w + 1
482
+
483
+ # Reshape column
484
+ col = col.T.reshape(batch_size, out_h, out_w, channels, kernel_h, kernel_w)
485
+ col = col.transpose(0, 3, 4, 5, 1, 2)
486
+
487
+ # Initialize image
488
+ img = np.zeros(input_shape)
489
+
490
+ # Fill image
491
+ for i in range(kernel_h):
492
+ i_max = i + stride_h * out_h
493
+ for j in range(kernel_w):
494
+ j_max = j + stride_w * out_w
495
+ img[:, :, i:i_max:stride_h, j:j_max:stride_w] += col[:, :, i, j, :, :]
496
+
497
+ return img
498
+
499
+
500
+ # ============================================================================
501
+ # DEPTHWISE AND SEPARABLE CONVOLUTIONS
502
+ # ============================================================================
503
+
504
+ def depthwise_conv2d(
505
+ input: np.ndarray,
506
+ kernel: np.ndarray,
507
+ stride: Union[int, Tuple[int, int]] = 1,
508
+ padding: Union[str, int, Tuple[int, int]] = 0
509
+ ) -> np.ndarray:
510
+ """
511
+ Depthwise 2D Convolution
512
+
513
+ Applies a separate filter to each input channel.
514
+ Used in MobileNets for efficiency.
515
+
516
+ Args:
517
+ input: Input tensor of shape (batch, in_channels, height, width)
518
+ kernel: Kernel tensor of shape (in_channels, 1, kernel_h, kernel_w)
519
+ stride: Stride of the convolution
520
+ padding: Padding added to input
521
+
522
+ Returns:
523
+ Output tensor of shape (batch, in_channels, out_height, out_width)
524
+
525
+ Example:
526
+ >>> input = np.random.randn(8, 32, 56, 56)
527
+ >>> kernel = np.random.randn(32, 1, 3, 3) # One filter per channel
528
+ >>> output = depthwise_conv2d(input, kernel, stride=1, padding='same')
529
+ >>> print(output.shape) # (8, 32, 56, 56)
530
+ """
531
+ batch_size, in_channels, _, _ = input.shape
532
+
533
+ # Apply convolution to each channel separately
534
+ outputs = []
535
+ for c in range(in_channels):
536
+ channel_input = input[:, c:c+1, :, :]
537
+ channel_kernel = kernel[c:c+1, :, :, :]
538
+ channel_output = conv2d(channel_input, channel_kernel, stride, padding)
539
+ outputs.append(channel_output)
540
+
541
+ return np.concatenate(outputs, axis=1)
542
+
543
+
544
+ def separable_conv2d(
545
+ input: np.ndarray,
546
+ depthwise_kernel: np.ndarray,
547
+ pointwise_kernel: np.ndarray,
548
+ stride: Union[int, Tuple[int, int]] = 1,
549
+ padding: Union[str, int, Tuple[int, int]] = 0
550
+ ) -> np.ndarray:
551
+ """
552
+ Separable 2D Convolution (Depthwise + Pointwise)
553
+
554
+ Efficient convolution used in MobileNets.
555
+
556
+ Args:
557
+ input: Input tensor of shape (batch, in_channels, height, width)
558
+ depthwise_kernel: Depthwise kernel (in_channels, 1, kernel_h, kernel_w)
559
+ pointwise_kernel: Pointwise kernel (out_channels, in_channels, 1, 1)
560
+ stride: Stride of the depthwise convolution
561
+ padding: Padding for depthwise convolution
562
+
563
+ Returns:
564
+ Output tensor of shape (batch, out_channels, out_height, out_width)
565
+
566
+ Example:
567
+ >>> input = np.random.randn(8, 32, 56, 56)
568
+ >>> dw_kernel = np.random.randn(32, 1, 3, 3)
569
+ >>> pw_kernel = np.random.randn(64, 32, 1, 1)
570
+ >>> output = separable_conv2d(input, dw_kernel, pw_kernel)
571
+ >>> print(output.shape) # (8, 64, 56, 56)
572
+ """
573
+ # Depthwise convolution
574
+ depthwise_output = depthwise_conv2d(input, depthwise_kernel, stride, padding)
575
+
576
+ # Pointwise convolution (1x1)
577
+ pointwise_output = conv2d(depthwise_output, pointwise_kernel, stride=1, padding=0)
578
+
579
+ return pointwise_output
580
+
581
+
582
+ # ============================================================================
583
+ # UTILITY FUNCTIONS
584
+ # ============================================================================
585
+
586
+ def calculate_output_size(
587
+ input_size: int,
588
+ kernel_size: int,
589
+ stride: int = 1,
590
+ padding: int = 0,
591
+ dilation: int = 1
592
+ ) -> int:
593
+ """
594
+ Calculate output size after convolution or pooling
595
+
596
+ Args:
597
+ input_size: Input dimension size
598
+ kernel_size: Kernel dimension size
599
+ stride: Stride
600
+ padding: Padding
601
+ dilation: Dilation
602
+
603
+ Returns:
604
+ Output dimension size
605
+
606
+ Example:
607
+ >>> out_size = calculate_output_size(224, 3, stride=2, padding=1)
608
+ >>> print(out_size) # 112
609
+ """
610
+ return (input_size + 2 * padding - dilation * (kernel_size - 1) - 1) // stride + 1
611
+
612
+
613
+ # Aliases for convenience
614
+ maxpool2d = max_pool2d
615
+ avgpool2d = avg_pool2d
616
+ global_avgpool = global_avg_pool2d
617
+ global_maxpool = global_max_pool2d
618
+ depthwise_conv = depthwise_conv2d
619
+ separable_conv = separable_conv2d
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ilovetools
3
- Version: 0.2.18
3
+ Version: 0.2.19
4
4
  Summary: A comprehensive Python utility library with modular tools for AI/ML, data processing, and daily programming needs
5
5
  Home-page: https://github.com/AliMehdi512/ilovetools
6
6
  Author: Ali Mehdi
@@ -11,7 +11,7 @@ Project-URL: Repository, https://github.com/AliMehdi512/ilovetools
11
11
  Project-URL: Issues, https://github.com/AliMehdi512/ilovetools/issues
12
12
  Project-URL: Bug Reports, https://github.com/AliMehdi512/ilovetools/issues
13
13
  Project-URL: Source, https://github.com/AliMehdi512/ilovetools
14
- Keywords: utilities,tools,ai,ml,data-processing,automation,attention-mechanism,self-attention,multi-head-attention,transformers,bert,gpt,positional-encoding
14
+ Keywords: utilities,tools,ai,ml,data-processing,automation,cnn,convolutional-neural-networks,conv2d,pooling,computer-vision,image-processing
15
15
  Classifier: Development Status :: 3 - Alpha
16
16
  Classifier: Intended Audience :: Developers
17
17
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
@@ -34,6 +34,7 @@ ilovetools/ml/activations.py
34
34
  ilovetools/ml/anomaly_detection.py
35
35
  ilovetools/ml/attention.py
36
36
  ilovetools/ml/clustering.py
37
+ ilovetools/ml/cnn.py
37
38
  ilovetools/ml/cross_validation.py
38
39
  ilovetools/ml/dimensionality.py
39
40
  ilovetools/ml/ensemble.py
@@ -66,6 +67,7 @@ ilovetools/web/url_shortener.py
66
67
  tests/__init__.py
67
68
  tests/test_activations.py
68
69
  tests/test_attention.py
70
+ tests/test_cnn.py
69
71
  tests/test_gradient_descent.py
70
72
  tests/test_loss_functions.py
71
73
  tests/test_neural_network.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ilovetools"
7
- version = "0.2.18"
7
+ version = "0.2.19"
8
8
  description = "A comprehensive Python utility library with modular tools for AI/ML, data processing, and daily programming needs"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -12,7 +12,7 @@ license = "MIT"
12
12
  authors = [
13
13
  {name = "Ali Mehdi", email = "ali.mehdi.dev579@gmail.com"}
14
14
  ]
15
- keywords = ["utilities", "tools", "ai", "ml", "data-processing", "automation", "attention-mechanism", "self-attention", "multi-head-attention", "transformers", "bert", "gpt", "positional-encoding"]
15
+ keywords = ["utilities", "tools", "ai", "ml", "data-processing", "automation", "cnn", "convolutional-neural-networks", "conv2d", "pooling", "computer-vision", "image-processing"]
16
16
  classifiers = [
17
17
  "Development Status :: 3 - Alpha",
18
18
  "Intended Audience :: Developers",