I am trying to implement IOC Network and thus am required to impose a non negative weight rule for all the layers except the first(along with ELU as activation function to allow flow of negative values)
I have got a tensorflow code up and running perfectly, which is:
class WeightClip(Constraint):
def __init__(self, c=100):
self.c = c
def __call__(self, p):
return K.clip(p, 0, self.c)
def get_config(self):
return {'name': self.__class__.__name__,'c': self.c}
def get_model(model_select):
inp_1 = Input(shape=(2,))
l11 = Dense(8, activation='elu',kernel_initializer='glorot_uniform')(inp_1)
if model_select == 'NN':
l12 = Dense(8, activation='elu',kernel_initializer='glorot_uniform')(l11)
l13 = Dense(8, activation='elu',kernel_initializer='glorot_uniform')(l12)
out = Dense(1, activation='sigmoid',kernel_initializer='glorot_uniform')(l13)
elif(model_select == 'IOC'):
l12 = Dense(8, activation='elu',kernel_initializer='glorot_uniform',W_constraint = WeightClip(2))(l11)
l13 = Dense(8, activation='elu',kernel_initializer='glorot_uniform',W_constraint = WeightClip(2))(l12)
out = Dense(1, activation='sigmoid',kernel_initializer='glorot_uniform',W_constraint = WeightClip(2))(l13)
else:
print ("invalid model")
return 0
model = Model(inputs=[inp_1], outputs=[out])
return model
However as suggest in this post, I tried to make my Weight Constraint class which I’m applying after every iteration.
My Pytorch code looks like:
class weightConstraint(object):
def __init__(self):
pass
def __call__(self,module):
if hasattr(module,'weight'):
# print("Entered")
w=module.weight.data
# w[torch.where(w<0)] = 0
w=w.clamp(min = 0)
module.weight.data=w
class Net(nn.Module):
def __init__(self,type_ = "single"):
super().__init__()
if type_ == "one-hot":
self.type = type_
elif type_ == "single":
self.type = type_
else:
print('{} type not defined. Proceeding with default single'.format(type_))
self.type = "single"
self.activation = F.elu
self.dense1 = nn.Linear(2, 8)
self.dense2 = nn.Linear(8, 8)
self.dense3 = nn.Linear(8, 8)
self.dense4 = nn.Linear(8, 8)
self.dense5 = nn.Linear(8, 1) if self.type == 'single' else nn.Linear(8, 2)
if self.type == 'single':
self.out_activation = nn.Sigmoid()
def forward(self,x):
out = x.view(x.shape[0],-1)
out = self.activation(self.dense1(out))
out = self.activation(self.dense2(out))
out = self.activation(self.dense3(out))
out = self.activation(self.dense4(out))
out = self.dense5(out)
if self.type == 'single':
out = self.out_activation(out)
return out
I am later using constraints = weightConstraint()
for the IOC case, followed by a loop on the modules, applying the constraint after every iteration.
def applyIOCConstraint(model, constraint):
if 'module' in model._modules.keys():
# if DataParallel is used
idx = 0
for key,val in model._modules['module']._modules.items():
if hasattr(val,'weight'):
if idx>0:
val.apply(constraint)
idx += 1
else:
idx = 0
for key,val in model._modules.items():
if hasattr(val,'weight'):
if idx>0:
val.apply(constraint)
idx += 1
However, this doesn’t work for some reason with my code. I’d like to know if you guys are spotting an incorrect usage in here, or otherwise, is their a option to add a weight constraint inherently in the layer itself