Mutating 3D slice without modifying the original

agolangf · · 433 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>So, In order to learn the golang I&#39;m porting an neural network project that I have.</p> <p>I&#39;m storing the network as an 3D matrix ([][][]float64). Ex:</p> <pre><code>[ [[] []] // 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 ] </code></pre> <p>I need to write a function that receives one network, mutate it&#39;s values and return A NEW mutated network without modifying the old one.</p> <p>Here is how I did it:</p> <pre><code>func Mutate(net [][][]float64) [][][]float64 { for l:=0;l&lt;len(net);l++{// fore layer... for n:=0;n&lt;len(net[l]);n++{// fore neuron... for a:=0;a&lt;len(net[l][n]);a++ {// fore element in neuron array... net[l][n][a] = 1// set new value } } } return net } </code></pre> <p>Here is the commented code for creating and mutating the network <a href="http://pastebin.com/sJsQQN1C" rel="nofollow">http://pastebin.com/sJsQQN1C</a></p> <p>And here is the test main function:</p> <pre><code>func main() { net := neuralArray.GenerateEmptyNet([]int{2,3,2,1}) fmt.Println(&#34;created net: &#34; ,net) net2 := neuralArray.Mutate(net) fmt.Println(&#34;old net:&#34; ,net) fmt.Println(&#34;new net:&#34;, net2) } </code></pre> <p>The result:</p> <pre><code>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]]] </code></pre> <p>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&#39;m clearly missing something here.</p> <p>Thanks for your time!</p> <hr/>**评论:**<br/><br/>Sythe2o0: <pre><p>Go does pass value copies, but slices are just pointers to some area of memory, so you end up copying that pointer. </p> <p>See this <a href="http://stackoverflow.com/questions/39993688/are-golang-slices-pass-by-value" rel="nofollow">stack overflow</a> post.</p></pre>Ablaek: <pre><p>Hm, so my best bet it to change to arrays, or to copy() the slices and build a new one.</p> <p>I&#39;m gonna redo the code with arrays. Thanks!</p> <p>EDIT:</p> <p>actually I just created a new slice, and used it as return value instead....</p></pre>gdey: <pre><p>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. </p> <p>Here is a great article on how slices work. <a href="https://blog.golang.org/go-slices-usage-and-internals" rel="nofollow">https://blog.golang.org/go-slices-usage-and-internals</a></p></pre>chewxy: <pre><p>You can use the <code>tensor</code> library:</p> <pre><code>a := tensor.New(tensor.Float64, tensor.WithShape(2,3,4)) b := a.Clone().(*tensor.Dense) b.Memset(1.0) return b </code></pre> <p>Best part is... you can just swap out <code>tensor.Float64</code> for other types like <code>tensor.Float32</code> and it&#39;ll still work the same (for the most part.. you still have to memset the correct values).</p> <p>More documentation can be found <a href="https://github.com/chewxy/gorgonia/blob/master/tensor/README.md" rel="nofollow">here</a></p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

433 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传