| 230 | |
| 231 | |
| 232 | def _tile_2d(pretrained_weights: torch.Tensor, new_weights: torch.Tensor, mode: TileMode) -> torch.Tensor: |
| 233 | assert pretrained_weights.dim() == 2, "Input tensor must be 2-dimensional" |
| 234 | input_height, input_width = pretrained_weights.shape |
| 235 | new_height, new_width = new_weights.shape |
| 236 | assert new_height >= input_height, "Desired height must be greater than or equal to input height" |
| 237 | assert new_width >= input_width, "Desired width must be greater than or equal to input width" |
| 238 | |
| 239 | if mode == TileMode.center_weights: |
| 240 | height_offset = (new_height - input_height) // 2 |
| 241 | width_offset = (new_width - input_width) // 2 |
| 242 | new_weights[height_offset : height_offset + input_height, width_offset : width_offset + input_width] = pretrained_weights # fmt: skip |
| 243 | return new_weights.clone() |
| 244 | elif mode == TileMode.tile_weights_from_edge: |
| 245 | repeat_height = (new_height + input_height - 1) // input_height |
| 246 | repeat_width = (new_width + input_width - 1) // input_width |
| 247 | tiled_tensor = pretrained_weights.repeat(repeat_height, repeat_width) |
| 248 | return tiled_tensor[:new_height, :new_width].clone() |
| 249 | elif mode == TileMode.tile_weights_from_middle: |
| 250 | # Calculate offsets to center the original tensor |
| 251 | height_offset = (new_height - input_height) // 2 |
| 252 | width_offset = (new_width - input_width) // 2 |
| 253 | |
| 254 | # Create a new tensor with the desired width and input height |
| 255 | horizontal_tiled = torch.zeros( |
| 256 | input_height, new_width, dtype=pretrained_weights.dtype, device=pretrained_weights.device |
| 257 | ) |
| 258 | |
| 259 | # Place the original tensor in the center horizontally |
| 260 | horizontal_tiled[:, width_offset : width_offset + input_width] = pretrained_weights |
| 261 | |
| 262 | # Tile the left and right sides |
| 263 | for i in range(width_offset): |
| 264 | horizontal_tiled[:, i] = horizontal_tiled[ |
| 265 | :, width_offset + input_width - 1 - (width_offset - i - 1) % input_width |
| 266 | ] |
| 267 | for i in range(width_offset + input_width, new_width): |
| 268 | horizontal_tiled[:, i] = horizontal_tiled[:, width_offset + (i - width_offset) % input_width] |
| 269 | |
| 270 | # Now tile vertically |
| 271 | result = torch.zeros(new_height, new_width, dtype=pretrained_weights.dtype, device=pretrained_weights.device) |
| 272 | result[height_offset : height_offset + input_height, :] = horizontal_tiled |
| 273 | |
| 274 | # Tile top |
| 275 | for i in range(height_offset): |
| 276 | row_to_copy = (input_height - 1) - (i % input_height) |
| 277 | result[height_offset - 1 - i, :] = horizontal_tiled[row_to_copy, :] |
| 278 | |
| 279 | # Tile bottom |
| 280 | for i in range(height_offset + input_height, new_height): |
| 281 | row_to_copy = (i - height_offset) % input_height |
| 282 | result[i, :] = horizontal_tiled[row_to_copy, :] |
| 283 | return result.clone() |
| 284 | |
| 285 | |
| 286 | def tile_fused_qkv( |