// Clone makes a copy of a into the receiver, overwriting the previous value of // the receiver. The clone operation does not make any restriction on shape. // // See the Cloner interface for more information. func (m *Dense) Clone(a Matrix) { r, c := a.Dims() mat := blas64.General{ Rows: r, Cols: c, Stride: c, } m.capRows, m.capCols = r, c switch a := a.(type) { case RawMatrixer: amat := a.RawMatrix() mat.Data = make([]float64, r*c) for i := 0; i < r; i++ { copy(mat.Data[i*c:(i+1)*c], amat.Data[i*amat.Stride:i*amat.Stride+c]) } case Vectorer: mat.Data = use(m.Mat.Data, r*c) for i := 0; i < r; i++ { a.Row(mat.Data[i*c:(i+1)*c], i) } default: mat.Data = use(m.Mat.Data, r*c) m.Mat = mat for i := 0; i < r; i++ { for j := 0; j < c; j++ { m.set(i, j, a.At(i, j)) } } return } m.Mat = mat }
func (c *controller1) wy(w []float64) blas64.General { m := blas64.General{ Rows: c.wyRows(), Cols: c.h1Size + 1, } m.Stride = m.Cols m.Data = w[c.wyOffset():c.wtm1Offset()] return m }
func (c *controller1) wh1(w []float64) blas64.General { m := blas64.General{ Rows: c.h1Size, Cols: c.wh1Cols(), } m.Stride = m.Cols m.Data = w[0:c.wyOffset()] return m }
// Clone makes a copy of a into the receiver, overwriting the previous value of // the receiver. The clone operation does not make any restriction on shape. // // See the Cloner interface for more information. func (m *Dense) Clone(a Matrix) { r, c := a.Dims() mat := blas64.General{ Rows: r, Cols: c, Stride: c, } m.capRows, m.capCols = r, c aU, trans := untranspose(a) switch aU := aU.(type) { case RawMatrixer: amat := aU.RawMatrix() // TODO(kortschak): Consider being more precise with determining whether a and m are aliases. // The current approach is that all RawMatrixers are considered potential aliases. // Note that below we assume that non-RawMatrixers are not aliases; this is not necessarily // true, but cases where it is not are not sensible. We should probably fix or document // this though. mat.Data = make([]float64, r*c) if trans { for i := 0; i < r; i++ { blas64.Copy(c, blas64.Vector{Inc: amat.Stride, Data: amat.Data[i : i+(c-1)*amat.Stride+1]}, blas64.Vector{Inc: 1, Data: mat.Data[i*c : (i+1)*c]}) } } else { for i := 0; i < r; i++ { copy(mat.Data[i*c:(i+1)*c], amat.Data[i*amat.Stride:i*amat.Stride+c]) } } case Vectorer: mat.Data = use(m.mat.Data, r*c) if trans { for i := 0; i < r; i++ { aU.Col(mat.Data[i*c:(i+1)*c], i) } } else { for i := 0; i < r; i++ { aU.Row(mat.Data[i*c:(i+1)*c], i) } } default: mat.Data = use(m.mat.Data, r*c) m.mat = mat for i := 0; i < r; i++ { for j := 0; j < c; j++ { m.set(i, j, a.At(i, j)) } } return } m.mat = mat }
// Clone makes a copy of a into the receiver, overwriting the previous value of // the receiver. The clone operation does not make any restriction on shape and // will not cause shadowing. // // See the Cloner interface for more information. func (m *Dense) Clone(a Matrix) { r, c := a.Dims() mat := blas64.General{ Rows: r, Cols: c, Stride: c, } m.capRows, m.capCols = r, c aU, trans := untranspose(a) switch aU := aU.(type) { case RawMatrixer: amat := aU.RawMatrix() mat.Data = make([]float64, r*c) if trans { for i := 0; i < r; i++ { blas64.Copy(c, blas64.Vector{Inc: amat.Stride, Data: amat.Data[i : i+(c-1)*amat.Stride+1]}, blas64.Vector{Inc: 1, Data: mat.Data[i*c : (i+1)*c]}) } } else { for i := 0; i < r; i++ { copy(mat.Data[i*c:(i+1)*c], amat.Data[i*amat.Stride:i*amat.Stride+c]) } } case *Vector: amat := aU.mat mat.Data = make([]float64, aU.n) blas64.Copy(aU.n, blas64.Vector{Inc: amat.Inc, Data: amat.Data}, blas64.Vector{Inc: 1, Data: mat.Data}) default: mat.Data = make([]float64, r*c) w := *m w.mat = mat for i := 0; i < r; i++ { for j := 0; j < c; j++ { w.set(i, j, a.At(i, j)) } } *m = w return } m.mat = mat }
func (c *convLayerRResult) propagateSingle(input, inputR, upstream, upstreamR, downstream, downstreamR linalg.Vector, rgrad autofunc.RGradient, grad autofunc.Gradient) { upstreamMat := blas64.General{ Rows: c.Layer.OutputWidth() * c.Layer.OutputHeight(), Cols: c.Layer.OutputDepth(), Stride: c.Layer.OutputDepth(), Data: upstream, } upstreamMatR := blas64.General{ Rows: c.Layer.OutputWidth() * c.Layer.OutputHeight(), Cols: c.Layer.OutputDepth(), Stride: c.Layer.OutputDepth(), Data: upstreamR, } if downstream != nil { inDeriv := c.Layer.inputToMatrix(input) filterMat := blas64.General{ Rows: len(c.Layer.Filters), Cols: c.Layer.FilterWidth * c.Layer.FilterHeight * c.Layer.InputDepth, Stride: c.Layer.FilterWidth * c.Layer.FilterHeight * c.Layer.InputDepth, Data: c.Layer.FilterVar.Vector, } blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, upstreamMat, filterMat, 0, inDeriv) flattened := NewTensor3Col(c.Layer.InputWidth, c.Layer.InputHeight, c.Layer.InputDepth, inDeriv.Data, c.Layer.FilterWidth, c.Layer.FilterHeight, c.Layer.Stride) copy(downstream, flattened.Data) blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, upstreamMatR, filterMat, 0, inDeriv) if c.FiltersR != nil { filterMat.Data = c.FiltersR blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, upstreamMat, filterMat, 1, inDeriv) } flattened = NewTensor3Col(c.Layer.InputWidth, c.Layer.InputHeight, c.Layer.InputDepth, inDeriv.Data, c.Layer.FilterWidth, c.Layer.FilterHeight, c.Layer.Stride) copy(downstreamR, flattened.Data) } filterGrad, hasFilterGrad := grad[c.Layer.FilterVar] filterRGrad, hasFilterRGrad := rgrad[c.Layer.FilterVar] var inMatrix blas64.General if hasFilterGrad || hasFilterRGrad { inMatrix = c.Layer.inputToMatrix(input) } if hasFilterGrad { destMat := blas64.General{ Rows: len(c.Layer.Filters), Cols: c.Layer.FilterWidth * c.Layer.FilterHeight * c.Layer.InputDepth, Stride: c.Layer.FilterWidth * c.Layer.FilterHeight * c.Layer.InputDepth, Data: filterGrad, } blas64.Gemm(blas.Trans, blas.NoTrans, 1, upstreamMat, inMatrix, 1, destMat) } if hasFilterRGrad { inMatrixR := c.Layer.inputToMatrix(inputR) destMat := blas64.General{ Rows: len(c.Layer.Filters), Cols: c.Layer.FilterWidth * c.Layer.FilterHeight * c.Layer.InputDepth, Stride: c.Layer.FilterWidth * c.Layer.FilterHeight * c.Layer.InputDepth, Data: filterRGrad, } blas64.Gemm(blas.Trans, blas.NoTrans, 1, upstreamMatR, inMatrix, 1, destMat) blas64.Gemm(blas.Trans, blas.NoTrans, 1, upstreamMat, inMatrixR, 1, destMat) } }
// svdCheck checks that the singular value decomposition correctly multiplies back // to the original matrix. func svdCheck(t *testing.T, thin bool, errStr string, m, n int, s, a, u []float64, ldu int, vt []float64, ldvt int, aCopy []float64, lda int) { sigma := blas64.General{ Rows: m, Cols: n, Stride: n, Data: make([]float64, m*n), } for i := 0; i < min(m, n); i++ { sigma.Data[i*sigma.Stride+i] = s[i] } uMat := blas64.General{ Rows: m, Cols: m, Stride: ldu, Data: u, } vTMat := blas64.General{ Rows: n, Cols: n, Stride: ldvt, Data: vt, } if thin { sigma.Rows = min(m, n) sigma.Cols = min(m, n) uMat.Cols = min(m, n) vTMat.Rows = min(m, n) } tmp := blas64.General{ Rows: m, Cols: n, Stride: n, Data: make([]float64, m*n), } ans := blas64.General{ Rows: m, Cols: n, Stride: lda, Data: make([]float64, m*lda), } copy(ans.Data, a) blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, uMat, sigma, 0, tmp) blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, tmp, vTMat, 0, ans) if !floats.EqualApprox(ans.Data, aCopy, 1e-8) { t.Errorf("Decomposition mismatch. Trim = %v, %s", thin, errStr) } if !thin { // Check that U and V are orthogonal. for i := 0; i < uMat.Rows; i++ { for j := i + 1; j < uMat.Rows; j++ { dot := blas64.Dot(uMat.Cols, blas64.Vector{Inc: 1, Data: uMat.Data[i*uMat.Stride:]}, blas64.Vector{Inc: 1, Data: uMat.Data[j*uMat.Stride:]}, ) if dot > 1e-8 { t.Errorf("U not orthogonal %s", errStr) } } } for i := 0; i < vTMat.Rows; i++ { for j := i + 1; j < vTMat.Rows; j++ { dot := blas64.Dot(vTMat.Cols, blas64.Vector{Inc: 1, Data: vTMat.Data[i*vTMat.Stride:]}, blas64.Vector{Inc: 1, Data: vTMat.Data[j*vTMat.Stride:]}, ) if dot > 1e-8 { t.Errorf("V not orthogonal %s", errStr) } } } } }