Source code for ingenii_quantum.tensor_networks.tucker_decomposition
from tensorly.decomposition import partial_tucker
import tensorly as tl
import torch
import torch.nn as nn
import numpy as np
[docs]
def tucker_decomposition_conv_layer(layer, ranks):
"""
Gets a convolutional layer, applies Tucker decomposition and returns the set of smaller layers.
Args:
layer (torch layer): convolutional layer to decompose
ranks (tuple): Ranks of the Tucker decomposition
Returns
nn.Sequential: object with the Tucker decomposition.
"""
tensors, _ = \
partial_tucker(tl.tensor(layer.weight.data), \
ranks, modes=[0, 1], init='svd')
core, [last, first] = tensors
# A pointwise convolution that reduces the channels from S to R3
first_layer = torch.nn.Conv2d(in_channels=first.shape[0], \
out_channels=first.shape[1], kernel_size=1,
stride=1, padding=0, dilation=layer.dilation, bias=False)
# A regular 2D convolution layer with R3 input channels and R3 output channels
core_layer = torch.nn.Conv2d(in_channels=core.shape[1], \
out_channels=core.shape[0], kernel_size=layer.kernel_size,
stride=layer.stride, padding=layer.padding, dilation=layer.dilation,
bias=False)
# A pointwise convolution that increases the channels from R4 to T
last_layer = torch.nn.Conv2d(in_channels=last.shape[1], \
out_channels=last.shape[0], kernel_size=1, stride=1,
padding=0, dilation=layer.dilation, bias=True)
if layer.bias is not None:
last_layer.bias.data = layer.bias.data
first_layer.weight.data = \
torch.transpose(torch.tensor(first), 1, 0).unsqueeze(-1).unsqueeze(-1)
last_layer.weight.data = torch.tensor(last).unsqueeze(-1).unsqueeze(-1)
core_layer.weight.data = torch.tensor(core)
new_layers = [first_layer, core_layer, last_layer]
return nn.Sequential(*new_layers)
[docs]
def count_params(network):
'''
Counts the number of parameters in the neural network
Args:
network (torch.nn): Neural network model
Returns:
float: Number of training parameters
'''
return np.sum(np.prod(p.size()) for p in network.parameters())