Learning parameters of sinusoids

I was wondering if there’s a proper way to learn the parameters of a sinusoid by gradient descent?
Here’s an example setup:

x = torch.arange(0, 5, 1 / sr) # =5s of audio
y = torch.sin(2 * np.pi * 2.85 * x) # want to get sinusoid with frequency 2.85
f = nn.Parameter(torch.tensor(2.0)) # initialize frequency parameter as 2.85

opt = torch.optim.AdamW([f], lr=0.001)
loss = nn.MSELoss()

for i in range(100):
    out = torch.sin(2 * np.pi * f * x)
    l = loss(out, y)

This won’t learn the correct value for f (2.85), but rather stay around 2.
Is there a way to set this up so it can learn through a periodic function?

Thanks for any input!

edit: simplified code somewhat

I think maybe evaluate the loss in frequency domain via fft will be easier, because directly train on time domain, in my experiences, is generally very hard