Last active
July 31, 2017 04:08
-
-
Save kendricktan/844af8a2f057205ece6d1672672d3162 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def k_competitive_layer(tensor, top_k, alpha, cuda=False): | |
""" | |
https://arxiv.org/pdf/1705.02033.pdf | |
Args: | |
tensor: Tensor | |
top_K: int | |
alpha: hyper param | |
""" | |
def k_update(tensor_, indices, top_k, alpha, largest=True, cuda=False): | |
""" | |
""" | |
tensor = tensor_.clone() | |
# Do we have enough top ks on each row | |
# to perform topk | |
has_enough_top_ks = torch.sum(indices, 1) | |
for i in range(has_enough_top_ks.size(0)): | |
if has_enough_top_ks[i].data[0] > top_k: | |
# Current tensor and indices | |
c_tensor = tensor[i] | |
if largest: | |
c_indices = c_tensor > 0 | |
else: | |
c_indices = c_tensor < 0 | |
# get top k/2 neg/pos activations | |
topk_val, topk_indices = torch.topk(c_tensor, int(top_k/2), dim=0, largest=largest) | |
# Get energy of lower (k/2) | |
E_ = torch.sum(c_tensor[c_indices]) - torch.sum(topk_val) | |
E_ = E_.data[0] | |
# Create a matrix to store energies | |
energies = Variable(torch.zeros(c_tensor.size())) | |
energy_var_placeholder = Variable(torch.zeros(topk_indices.size())) | |
if cuda: | |
energies = energies.cuda() | |
energy_var_placeholder = energy_var_placeholder.cuda() | |
energies = energies.scatter(0, topk_indices, energy_var_placeholder + (E_*alpha)) | |
# Create mask to zero non top k activations | |
zero_mask = c_indices.scatter(0, topk_indices, energy_var_placeholder.byte()) | |
# Zero out non top-k neurons | |
c_tensor = c_tensor.masked_fill(zero_mask, 0) | |
# Add energies | |
tensor[i] = c_tensor + energies | |
return tensor | |
# Get indices | |
pos_indices = tensor > 0 | |
tensor = k_update(tensor, pos_indices, top_k, alpha, largest=True, cuda=cuda) | |
neg_indices = tensor < 0 | |
tensor = k_update(tensor, neg_indices, top_k, alpha, largest=False, cuda=cuda) | |
return tensor | |
class KateAutoencoder(nn.Module): | |
def __init__(self, n_tokens, n_hidden, top_k, alpha=1): | |
super().__init__() | |
assert (n_tokens > top_k) | |
self.alpha = alpha | |
self.top_k = top_k | |
self.n_tokens = n_tokens | |
self.fc1 = nn.Linear(n_tokens, n_hidden) | |
self.fc2 = nn.Linear(n_hidden, n_tokens) | |
def forward(self, x): | |
z = F.tanh(self.fc1(x)) | |
z_hat = k_competitive_layer(z, self.top_k, self.alpha, cuda=CUDA) | |
x_hat = F.sigmoid(self.fc2(z_hat)) | |
return x_hat |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment