So, In order to learn the golang I'm porting an neural network project that I have.
I'm storing the network as an 3D matrix ([][][]float64). Ex:
[
[[] []] // layer 0
[[0 0 0] [0 0 0] [0 0 0]] // layer 1
[[0 0 0 0] [0 0 0 0]] // layer 2
[[0 0 0]] // layer 3
]
I need to write a function that receives one network, mutate it's values and return A NEW mutated network without modifying the old one.
Here is how I did it:
func Mutate(net [][][]float64) [][][]float64 {
for l:=0;l<len(net);l++{// fore layer...
for n:=0;n<len(net[l]);n++{// fore neuron...
for a:=0;a<len(net[l][n]);a++ {// fore element in neuron array...
net[l][n][a] = 1// set new value
}
}
}
return net
}
Here is the commented code for creating and mutating the network http://pastebin.com/sJsQQN1C
And here is the test main function:
func main() {
net := neuralArray.GenerateEmptyNet([]int{2,3,2,1})
fmt.Println("created net: " ,net)
net2 := neuralArray.Mutate(net)
fmt.Println("old net:" ,net)
fmt.Println("new net:", net2)
}
The result:
go run src/main/main2.go
created net: [[[] []] [[0 0 0] [0 0 0] [0 0 0]] [[0 0 0 0] [0 0 0 0]] [[0 0 0]]]
old net: [[[] []] [[1 1 1] [1 1 1] [1 1 1]] [[1 1 1 1] [1 1 1 1]] [[1 1 1]]]
new net: [[[] []] [[1 1 1] [1 1 1] [1 1 1]] [[1 1 1 1] [1 1 1 1]] [[1 1 1]]]
As you see, the old got mutated too. What is causing this behavior? I heard that passing a value as parameter rather than pointer creates a separated clone. But I'm clearly missing something here.
Thanks for your time!
评论:
Sythe2o0:
Ablaek:Go does pass value copies, but slices are just pointers to some area of memory, so you end up copying that pointer.
See this stack overflow post.
gdey:Hm, so my best bet it to change to arrays, or to copy() the slices and build a new one.
I'm gonna redo the code with arrays. Thanks!
EDIT:
actually I just created a new slice, and used it as return value instead....
chewxy:A slice is really a struct that has a pointer to a backing array and two other fields that record the length and capacity of the backing error. So when you pass a slice, you are just passing a copy of this struct. So, both struct point to the original backing array.
Here is a great article on how slices work. https://blog.golang.org/go-slices-usage-and-internals
You can use the
tensor
library:a := tensor.New(tensor.Float64, tensor.WithShape(2,3,4)) b := a.Clone().(*tensor.Dense) b.Memset(1.0) return b
Best part is... you can just swap out
tensor.Float64
for other types liketensor.Float32
and it'll still work the same (for the most part.. you still have to memset the correct values).More documentation can be found here
