Built-in optimizers have no idea about constraints, so any other solution would be more cumbersome.
You can improve things a bit:
def __init__(self):
    self.my_param= nn.Parameter(torch.logit(torch.tensor([0.5])) #inverse of sigmoid
@property
def gamma(self):
    return self.my_param.sigmoid()

though I don’t like uncached @property there
PS: cuda() can be omitted and done on a module, and requires_grad=True is unnecessary