先给出SimpleMatrix.cs的开头,定义总行数、总列数、所有数据(double类型)
using System; using System.IO; namespace NeuralDefs.Matrix { public class SimpleMatrix : IMatrix { public int Row { get; set; } public int Column { get; set; } public double[,] Data { get; set; }
其中用了IMatrix矩阵来组织,因为我还写了稀疏矩阵的。关于这个接口在介绍稀疏矩阵时候再写
1、首先实现简单矩阵的最基本功能——赋值和输出
我经常用csv格式的文件,用自然方式存储和查看矩阵
public SimpleMatrix(int row, int col) { // init matrix Row = row; Column = col; Data = new double[row, col]; for (var i = 0; i < row; i++) { for (var j = 0; j < col; j++) { Data[i, j] = 0; } } } public SimpleMatrix(string fileName) { //var splitUnit = '\t'; var splitUnit = ','; // count columns var srCol = new StreamReader(fileName); var firstLine = srCol.ReadLine(); if (firstLine != null) { var firstArray = firstLine.Split(splitUnit); Column = firstArray.Length; } srCol.Close(); // count rows Row = 0; var srRow = new StreamReader(fileName); while (srRow.ReadLine() != null) { Row++; } srRow.Close(); // init matrix Data = new double[Row, Column]; // fill matrix var srData = new StreamReader(fileName); var curRow = 0; string line; while ((line = srData.ReadLine()) != null) { var lineArray = line.Split(splitUnit); for (var i = 0; i < lineArray.Length; i++) { Data[curRow, i] = double.Parse(lineArray[i]); } curRow++; } srData.Close(); } public void WriteTo(string path) { var fs = new FileStream(path, FileMode.Create); var sw = new StreamWriter(fs); for (var i = 0; i < Row; i++) { sw.WriteLine(this.RowVector(i).ToSingleLineRow()); } sw.Close(); fs.Close(); }
2、用索引器取下标
public double this[int row, int column] { get { return Data[row, column]; } set { Data[row, column] = value; } }
3、随机化(用于神经网络赋初值等用途)
public void Randomize() { var rm = new Random(); for (var i = 0; i < Row; i++) { for (var j = 0; j < Column; j++) { Data[i, j] = rm.Next(-100, 100) / 1000.0; } } }
4、取某行
public SimpleMatrix RowVector(int row) { var result = new SimpleMatrix(1, Column); for (var i = 0; i < Column; i++) { result[0, i] = Data[row, i]; } return result; }
5、减法
public static SimpleMatrix operator -(SimpleMatrix a, SimpleMatrix b) { var minus = new SimpleMatrix(a.Row, a.Column); for (var i = 0; i < minus.Row; i++) { for (var j = 0; j < minus.Column; j++) { minus[i, j] = a[i, j] - b[i, j]; } } return minus; }
6、范数
public static double Norm2(SimpleMatrix a) { var norm = 0.0; for (var i = 0; i < a.Row; i++) { for (var j = 0; j < a.Column; j++) { norm += a[i, j] * a[i, j]; } } return Math.Sqrt(norm); }
7、连接两个向量
public static SimpleMatrix Link(SimpleMatrix vector1, SimpleMatrix vector2) { // check is vector if (vector1.Column != 1 || vector2.Column != 1) return null; var newRow = vector1.Row + vector2.Row; var result = new SimpleMatrix(newRow, 1); for (var i = 0; i < vector1.Row; i++) { result[i, 0] = vector1[i, 0]; } for (var i = 0; i < vector2.Row; i++) { result[vector1.Row + i, 0] = vector2[i, 0]; } return result; }
8、单元素矩阵
public static SimpleMatrix SingleValueMatrix(double val) { return new SimpleMatrix(1, 1) { Data = { [0, 0] = val } }; }
9、绝对值最大元
public static double MaxAbsMember(SimpleMatrix a) { var max = -1.0; foreach (var d in a.Data) { if (Math.Abs(d) > max) max = Math.Abs(d); } return max; }
10、矩阵转置
public static SimpleMatrix Transpose(SimpleMatrix a) { var result = new SimpleMatrix(a.Column, a.Row); for (var i = 0; i < result.Row; i++) { for (var j = 0; j < result.Column; j++) { result[i, j] = a[j, i]; } } return result; }