示例#1
0
// 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
}
示例#2
0
文件: cntl1.go 项目: philipz/ntm
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
}
示例#3
0
文件: cntl1.go 项目: philipz/ntm
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
}
示例#4
0
文件: dense.go 项目: idavydov/matrix
// 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
}
示例#5
0
// 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
}
示例#6
0
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)
	}
}
示例#7
0
// 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)
				}
			}
		}
	}
}