This problem is much harder to solve. You'll find that in order to get a feel for how our output improves, running for several epochs is very valuable here since we can write our model's output as the training takes place, with the following code:
for j := 0; j < 1; j++ {
rowT, _ := yOutput.Slice(sli{j, j + 1})
row := rowT.Data().([]float64)
img := visualizeRow(row)
f, _ := os.OpenFile(fmt.Sprintf("training/%d - %d - %d training.jpg", j, b, i), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
jpeg.Encode(f, img, &jpeg.Options{jpeg.DefaultQuality})
f.Close()
}
As we're training the model, we can now watch it improve over every epoch:
You can see that we start with almost pure noise, and then very quickly get to a blurry shape, which slowly gets sharper as we progress through the epochs.