private static NdArray <Real> LocalSum(NdArray <Real> input, int axis) { int[] resultShape = new int[input.Shape.Length - 1]; for (int i = 0, j = 0; i < input.Shape.Length; i++) { if (i != axis) { resultShape[j++] = input.Shape[i]; } } NdArray <Real> result = new NdArray <Real>(resultShape, input.BatchCount); for (int i = 0; i < input.Length; i++) { List <int> index = new List <int>(input.GetDimensionsIndex(i)); index.RemoveAt(axis); int localIndex = result.GetLocalIndex(0, index.ToArray()); for (int batchCount = 0; batchCount < input.BatchCount; batchCount++) { result.Data[batchCount * result.Length + localIndex] += input.Data[batchCount * input.Length + i]; if (input.Grad != null) { result.Grad[batchCount * result.Length + localIndex] += input.Grad[batchCount * input.Length + i]; } } } return(result); }
private static NdArray Sum(NdArray a, int axis) { int[] resultShape = new int[a.Shape.Length - 1]; for (int i = 0, j = 0; i < a.Shape.Length; i++) { if (i != axis) { resultShape[j++] = a.Shape[i]; } } NdArray result = new NdArray(resultShape, a.BatchCount); for (int i = 0; i < a.Length; i++) { List <int> index = new List <int>(a.GetDimensionsIndex(i)); index.RemoveAt(axis); int localIndex = result.GetLocalIndex(0, index.ToArray()); for (int batchCount = 0; batchCount < a.BatchCount; batchCount++) { result.Data[batchCount * result.Length + localIndex] += a.Data[batchCount * a.Length + i]; result.Grad[batchCount * result.Length + localIndex] += a.Grad[batchCount * a.Length + i]; } } return(result); }
public static NdArray Transpose(NdArray input, params int[] dimensions) { #if DEBUG if (input.Shape.Length != dimensions.Length) { throw new Exception("次元数がマッチしていません"); } for (int i = 0; i < dimensions.Length; i++) { //自身の中にダブりがないか for (int j = i + 1; j < dimensions.Length; j++) { if (dimensions[i] == dimensions[j]) { throw new Exception("指定された要素がダブっています"); } } //範囲チェック if (dimensions[i] >= input.Shape.Length || dimensions[i] < 0) { throw new Exception("指定された要素が範囲を超えています"); } } #endif int[] transposedDimensions = new int[input.Shape.Length]; for (int j = 0; j < input.Shape.Length; j++) { transposedDimensions[j] = input.Shape[dimensions[j]]; } NdArray resultMatrix = new NdArray(transposedDimensions); for (int b = 0; b < input.BatchCount; b++) { for (int i = 0; i < input.Length; i++) { int[] indecies = input.GetDimensionsIndex(i); int[] transposedIndex = new int[input.Shape.Length]; for (int j = 0; j < input.Shape.Length; j++) { transposedIndex[j] = indecies[dimensions[j]]; } resultMatrix.Data[resultMatrix.GetLocalIndex(b, transposedIndex)] = input.Data[input.GetLocalIndex(b, indecies)]; } } return(resultMatrix); }
public static NdArray Concatenate(NdArray a, NdArray b, int axis) { int[] shapeList = a.Shape.ToArray(); shapeList[axis] += b.Shape[axis]; #if DEBUG for (int i = 0; i < a.Shape.Length; i++) { if (i != axis && a.Shape[i] != b.Shape[i]) { throw new Exception("配列の大きさがマッチしていません"); } } if (a.BatchCount != b.BatchCount) { throw new Exception("バッチの大きさがマッチしていません"); } #endif NdArray result = new NdArray(shapeList, a.BatchCount); for (int batchCount = 0; batchCount < a.BatchCount; batchCount++) { int aInputBatchoffset = batchCount * a.Length; int bInputBatchoffset = batchCount * b.Length; for (int i = 0; i < a.Length; i++) { int resultindex = result.GetLocalIndex(batchCount, a.GetDimensionsIndex(i)); result.Data[resultindex] = a.Data[i + aInputBatchoffset]; result.Grad[resultindex] = a.Grad[i + aInputBatchoffset]; } for (int i = 0; i < b.Length; i++) { int[] tmpIndex = b.GetDimensionsIndex(i); tmpIndex[axis] += a.Shape[axis]; int resultIndex = result.GetLocalIndex(batchCount, tmpIndex); result.Data[resultIndex] = b.Data[i + bInputBatchoffset]; result.Grad[resultIndex] = b.Grad[i + bInputBatchoffset]; } } return(result); }
NdArray ForwardCpu(NdArray val) { int[] resultShape; if (val.Shape.Length > this.Shape.Length) { //入力の方が大きい resultShape = val.Shape.ToArray(); int offset = val.Shape.Length - this.Shape.Length; for (int i = offset; i < resultShape.Length; i++) { if (resultShape[i] == 1) { resultShape[i] = this.Shape[i - offset]; } #if DEBUG else if (this.Shape[i - offset] != 1 && resultShape[i] != this.Shape[i - offset]) { throw new Exception("変換不可能な組み合わせです"); } #endif } } else { //指定の方が大きい resultShape = this.Shape.ToArray(); int offset = this.Shape.Length - val.Shape.Length; for (int i = offset; i < resultShape.Length; i++) { if (resultShape[i] == 1) { resultShape[i] = val.Shape[i - offset]; } #if DEBUG else if (val.Shape[i - offset] != 1 && resultShape[i] != val.Shape[i - offset]) { throw new Exception("変換不可能な組み合わせです"); } #endif } } NdArray result = new NdArray(resultShape, val.BatchCount, this); int indexOffset = result.Shape.Length - val.Shape.Length; for (int batchCount = 0; batchCount < result.BatchCount; batchCount++) { for (int i = 0; i < result.Length; i++) { int[] baseIndex = result.GetDimensionsIndex(i); int tmpIndexLastIndex = val.Shape.Length - 1; int valIndex = batchCount * val.Length; int rankoffset = 1; for (int j = 0; j < val.Shape.Length; j++) { if (val.Shape[tmpIndexLastIndex] > 1) { valIndex += baseIndex[tmpIndexLastIndex + indexOffset] * rankoffset; } rankoffset *= val.Shape[tmpIndexLastIndex--]; } result.Data[batchCount * result.Length + i] = val.Data[valIndex]; } } return(result); }