@@ -36,7 +36,224 @@ def tile(input: Tensor, kernel: Tuple[int, int]) -> Tuple[Tensor, int, int]:
36
36
assert height % kh == 0
37
37
assert width % kw == 0
38
38
# TODO: Implement for Task 4.3.
39
- raise NotImplementedError ("Need to implement for Task 4.3" )
39
+ input = input .contiguous ()
40
+
41
+ new_height = height // kh
42
+ new_width = width // kw
43
+ out = input .view (batch , channel , new_height , kh , new_width , kw )
44
+ out = out .permute (0 , 1 , 2 , 4 , 3 , 5 )
45
+ out = out .contiguous ()
46
+ out = out .view (batch , channel , new_height , new_width , kh * kw )
47
+
48
+ return out , new_height , new_width
40
49
41
50
42
51
# TODO: Implement for Task 4.3.
52
+ def avgpool2d (input : Tensor , kernel : Tuple [int , int ]) -> Tensor :
53
+ """Apply average pooling on the 2D input tensor.
54
+
55
+ Parameters
56
+ ----------
57
+ input : Tensor
58
+ Input tensor with shape [batch, channels, height, width].
59
+ kernel : Tuple[int, int]
60
+ Tuple specifying the height and width of the pooling kernel.
61
+
62
+ Returns
63
+ -------
64
+ Tensor
65
+ Tensor after applying average pooling, with reduced height and width
66
+ depending on the kernel size.
67
+ Shape: [batch, channels, new_height, new_width]
68
+
69
+ """
70
+ tiled , new_height , new_width = tile (input , kernel )
71
+ pooled = tiled .mean (dim = 4 )
72
+ return pooled .view (input .shape [0 ], input .shape [1 ], new_height , new_width )
73
+
74
+
75
+ class Max (Function ):
76
+ @staticmethod
77
+ def forward (ctx : Context , t : Tensor , dim : Tensor ) -> Tensor :
78
+ """Compute the maximum values along a specified dimension.
79
+
80
+ Parameters
81
+ ----------
82
+ ctx : Context
83
+ Context object for storing intermediate values for the backward pass.
84
+ t : Tensor
85
+ Input tensor.
86
+ dim : Tensor
87
+ Dimension along which to compute the maximum.
88
+
89
+ Returns
90
+ -------
91
+ Tensor
92
+ A tensor containing the maximum values along the specified dimension.
93
+
94
+ """
95
+ d = int (dim .item ())
96
+ res = FastOps .reduce (operators .max , start = - 1e30 )(t , d )
97
+ ctx .save_for_backward (t , dim , res )
98
+ return res
99
+
100
+ @staticmethod
101
+ def backward (ctx : Context , grad_output : Tensor ) -> Tuple [Tensor , float ]:
102
+ """Compute the gradient of the max operation.
103
+
104
+ Parameters
105
+ ----------
106
+ ctx : Context
107
+ Context object containing saved values from the forward pass.
108
+ grad_output : Tensor
109
+ Gradient of the loss with respect to the output of the max operation.
110
+
111
+ Returns
112
+ -------
113
+ Tuple[Tensor, float]
114
+ - Gradient of the loss with respect to the input tensor.
115
+ - A float representing the gradient with respect to the dimension, which is always 0.
116
+
117
+ """
118
+ t , dim , max_val = ctx .saved_values
119
+ d = int (dim .item ())
120
+ mask = t == max_val
121
+ sum_mask = mask .sum (dim = d )
122
+ grad_input = mask * (grad_output / sum_mask )
123
+ return grad_input , 0.0
124
+
125
+
126
+ def max (t : Tensor , dim : int ) -> Tensor :
127
+ """Apply the max function along a specified dimension.
128
+
129
+ Parameters
130
+ ----------
131
+ t : Tensor
132
+ Input tensor.
133
+ dim : int
134
+ Dimension along which to compute the maximum.
135
+
136
+ Returns
137
+ -------
138
+ Tensor
139
+ Tensor containing the maximum values along the specified dimension.
140
+
141
+ """
142
+ return Max .apply (t , tensor (dim ))
143
+
144
+
145
+ def argmax (t : Tensor , dim : int ) -> Tensor :
146
+ """Compute the indices of the maximum values along a specified dimension.
147
+
148
+ Parameters
149
+ ----------
150
+ t : Tensor
151
+ Input tensor.
152
+ dim : int
153
+ Dimension along which to compute the indices of the maximum.
154
+
155
+ Returns
156
+ -------
157
+ Tensor
158
+ Tensor containing one-hot encoded indices of the maximum values along the specified dimension.
159
+
160
+ """
161
+ m = max (t , dim )
162
+ expand_shape = list (m .shape )
163
+ expand_shape .insert (dim , t .shape [dim ])
164
+ mask = t == m
165
+ return mask
166
+
167
+
168
+ def softmax (t : Tensor , dim : int ) -> Tensor :
169
+ """Compute the softmax along a specified dimension.
170
+
171
+ Parameters
172
+ ----------
173
+ t : Tensor
174
+ Input tensor.
175
+ dim : int
176
+ Dimension along which to compute the softmax.
177
+
178
+ Returns
179
+ -------
180
+ Tensor
181
+ Tensor containing the softmax probabilities along the specified dimension.
182
+
183
+ """
184
+ exp_t = t .exp ()
185
+ sum_exp = exp_t .sum (dim = dim )
186
+ return exp_t / sum_exp
187
+
188
+
189
+ def logsoftmax (t : Tensor , dim : int ) -> Tensor :
190
+ """Compute the log of the softmax along a specified dimension.
191
+
192
+ Parameters
193
+ ----------
194
+ t : Tensor
195
+ Input tensor.
196
+ dim : int
197
+ Dimension along which to compute the logsoftmax.
198
+
199
+ Returns
200
+ -------
201
+ Tensor
202
+ Tensor containing the log of the softmax probabilities along the specified dimension.
203
+
204
+ """
205
+ m = max (t , dim = dim )
206
+ log_sum_exp = ((t - m ).exp ().sum (dim = dim )).log () + m
207
+ return t - log_sum_exp
208
+
209
+
210
+ def maxpool2d (input : Tensor , kernel : Tuple [int , int ]) -> Tensor :
211
+ """Apply max pooling on the 2D input tensor.
212
+
213
+ Parameters
214
+ ----------
215
+ input : Tensor
216
+ Input tensor with shape [batch, channels, height, width].
217
+ kernel : Tuple[int, int]
218
+ Tuple specifying the height and width of the pooling kernel.
219
+
220
+ Returns
221
+ -------
222
+ Tensor
223
+ Tensor after applying max pooling, with reduced height and width
224
+ depending on the kernel size.
225
+ Shape: [batch, channels, new_height, new_width]
226
+
227
+ """
228
+ tiled , new_height , new_width = tile (input , kernel )
229
+ pooled = max (tiled , dim = 4 )
230
+ return pooled .view (input .shape [0 ], input .shape [1 ], new_height , new_width )
231
+
232
+
233
+ def dropout (input : Tensor , p : float = 0.5 , ignore : bool = False ) -> Tensor :
234
+ """Apply dropout regularization to the input tensor.
235
+
236
+ Parameters
237
+ ----------
238
+ input : Tensor
239
+ Input tensor.
240
+ p : float, optional
241
+ Dropout probability (default is 0.5).
242
+ ignore : bool, optional
243
+ If True, bypass dropout (default is False).
244
+
245
+ Returns
246
+ -------
247
+ Tensor
248
+ Tensor with randomly zeroed elements scaled by 1 / (1 - p) to maintain expected value.
249
+
250
+ """
251
+ if p == 1.0 :
252
+ if not ignore :
253
+ return input .zeros (input .shape )
254
+ else :
255
+ return input
256
+ if ignore :
257
+ return input
258
+ mask = rand (input .shape , backend = input .backend ) > p
259
+ return input * mask * (1.0 / (1 - p ))
0 commit comments