/// <summary> /// Multiplies a sparse matrix by a row vector. /// </summary> /// <param name="A">The matrix.</param> /// <param name="v">The row vector.</param> /// <returns>The product row vector.</returns> public static RowVector operator *(RowVector v, SparseSquareMatrix A) { if (v == null) { throw new ArgumentNullException("v"); } if (A == null) { throw new ArgumentNullException("A"); } if (v.Dimension != A.Dimension) { throw new DimensionMismatchException(); } RowVector vA = new RowVector(A.Dimension); for (int i = 0; i < A.Dimension; i++) { SparseMatrixElement element = A.columns[i]; while (element != null) { vA[i] += element.Value * v[element.Row]; element = element.NextInColumn; } } return(vA); }
/// <summary> /// Multiplies any real, rectangular matrix by a row vector. /// </summary> /// <param name="v">The row vector.</param> /// <param name="A">The matrix.</param> /// <returns>The product row vector.</returns> public static RowVector operator *(RowVector v, AnyRectangularMatrix A) { if (v == null) { throw new ArgumentNullException(nameof(v)); } if (A == null) { throw new ArgumentNullException(nameof(A)); } if (v.Dimension != A.RowCount) { throw new DimensionMismatchException(); } RowVector vA = new RowVector(A.ColumnCount); for (int r = 0; r < A.RowCount; r++) { for (int c = 0; c < A.ColumnCount; c++) { vA[c] += v[r] * A[r, c]; } } return(vA); }
public void SparseSquareMatrixAgreement() { int d = 6; SparseSquareMatrix A = new SparseSquareMatrix(d); SquareMatrix B = new SquareMatrix(d); Random rng = new Random(1); for (int i = 0; i < 2 * d; i++) { int r = (int) Math.Floor(rng.NextDouble() * d); int c = (int) Math.Floor(rng.NextDouble() * d); A[r, c] = 2.0 * rng.NextDouble() - 1.0; B[r, c] = A[r, c]; } RowVector u = new RowVector(d); ColumnVector v = new ColumnVector(d); for (int i = 0; i < d; i++) { u[i] = 2.0 * rng.NextDouble() - 1.0; v[i] = 2.0 * rng.NextDouble() - 1.0; } RowVector uA = u * A; RowVector uB = u * B; Assert.IsTrue(TestUtilities.IsNearlyEqual(uA, uB)); ColumnVector Av = A * v; ColumnVector Bv = B * v; Assert.IsTrue(TestUtilities.IsNearlyEqual(Av, Bv)); }
/// <summary> /// Returns a clone of the row vector. /// </summary> /// <returns>An independent row vector with the same components as the original.</returns> public RowVector Clone() { RowVector u = new RowVector(Dimension); for (int i = 0; i < Dimension; i++) { u[i] = this[i]; } return(u); }
/// <summary> /// Computes the product of a real number and a row vector. /// </summary> /// <param name="a">The real number.</param> /// <param name="v">The row vector.</param> /// <returns>The product of <paramref name="a"/> and <paramref name="v"/>.</returns> public static RowVector operator *(double a, RowVector v) { int d = v.Dimension; RowVector u = new RowVector(d); for (int i = 0; i < d; i++) { u[i] = a * v[i]; } return(u); }
/// <summary> /// Returns a vector representing a given row of the matrix. /// </summary> /// <param name="r">The (zero-based) row number to return.</param> /// <returns>An independent copy of the specified row.</returns> /// <remarks>The returned vector is not linked to the matrix. If an entry in the matrix is updated after this method /// is called, the returned object will continue to represent a row of the original, not the updated, matrix. Similiarly, /// updates to the elements of the returned vector will not update the original matrix.</remarks> public override RowVector Row(int r) { if ((r < 0) || (r >= dimension)) { throw new ArgumentOutOfRangeException("r"); } RowVector row = new RowVector(dimension); for (int c = 0; c < dimension; c++) { row[c] = this[r, c]; } return(row); }
/// <summary> /// Gets a copy of the specified row. /// </summary> /// <param name="r">The (zero-based) row index.</param> /// <returns>An independent copy of the specified row.</returns> public virtual RowVector Row(int r) { if ((r < 0) || (r >= RowCount)) { throw new ArgumentOutOfRangeException(nameof(r)); } RowVector v = new RowVector(ColumnCount); for (int c = 0; c < ColumnCount; c++) { v[c] = this[r, c]; } return(v); }
public Network(int windowSize, int imagesNumber, double learningCoefficient, double maxError, int maxIterations) { this.windowSize = windowSize; this.imagesNumber = imagesNumber; this.learningCoefficient = learningCoefficient; this.maxError = maxError; this.maxIterations = maxIterations; weightMatrix1 = new RectangularMatrix(imagesNumber, windowSize + imagesNumber); CreateRandomMatrix(weightMatrix1); weightMatrix2 = new RowVector(imagesNumber); CreateRandomRowVector(weightMatrix2); contextNeurons = new ColumnVector(imagesNumber); }
/// <summary> /// Computes the difference of two row vectors. /// </summary> /// <param name="v1">The first row vector.</param> /// <param name="v2">The second row vector.</param> /// <returns>The difference of <paramref name="v1"/> and <paramref name="v2"/>.</returns> public static RowVector operator -(RowVector v1, RowVector v2) { if (v1.Dimension != v2.Dimension) { throw new DimensionMismatchException(); } int d = v1.Dimension; RowVector u = new RowVector(d); for (int i = 0; i < d; i++) { u[i] = v1[i] - v2[i]; } return(u); }
// multliplication by a matrix /// <summary> /// Computes the product of a row vector and a matrix. /// </summary> /// <param name="v">The row vector.</param> /// <param name="M">The matrix.</param> /// <returns>The product vM.</returns> public static RowVector operator *(RowVector v, IMatrix M) { if (v.Dimension != M.RowCount) { throw new DimensionMismatchException(); } RowVector u = new RowVector(M.ColumnCount); for (int i = 0; i < u.Dimension; i++) { u[i] = 0.0; for (int j = 0; j < v.Dimension; j++) { u[i] += v[j] * M[j, i]; } } return(u); }
private void CreateRandomRowVector(RowVector weightMatrix) { Random rand = new Random(); for (int j = 0; j < weightMatrix.ColumnCount; j++) { weightMatrix[j] = rand.NextDouble() * 0.1; } }
/// <summary> /// Multiplies any real, rectangular matrix by a row vector. /// </summary> /// <param name="v">The row vector.</param> /// <param name="A">The matrix.</param> /// <returns>The product row vector.</returns> public static RowVector operator *(RowVector v, AnyRectangularMatrix A) { if (v == null) throw new ArgumentNullException("v"); if (A == null) throw new ArgumentNullException("A"); if (v.Dimension != A.RowCount) throw new DimensionMismatchException(); RowVector vA = new RowVector(A.ColumnCount); for (int r = 0; r < A.RowCount; r++) { for (int c = 0; c < A.ColumnCount; c++) { vA[c] += v[r] * A[r, c]; } } return (vA); }
/// <summary> /// Solves Ax = b using iterative methods. /// </summary> /// <param name="rhs">The right-hand side vector b.</param> /// <returns>The solution vector x.</returns> /// <remarks> /// <para>In general, neither the inverse nor any decomposition of a sparse matrix is itself sparse. Therefore, /// to solve large, sparse linear systems, iterative methods are employed. An iterative method begins with /// an approximate or guessed solution vector and progresses toward an improved solution. Iterative methods /// are often successful at converging to a sufficiently accurate solution vector, but this is not guaranteed. /// If this method fails to converge, it throws a <see cref="NonconvergenceException"/>.</para> /// </remarks> /// <exception cref="ArgumentNullException"><paramref name="rhs"/> is null.</exception> /// <exception cref="DimensionMismatchException"><paramref name="rhs"/>'s dimension does not equal the matrix's dimension.</exception> /// <exception cref="NonconvergenceException">The method did not converge to a solution.</exception> public ColumnVector Solve(ColumnVector rhs) { if (rhs == null) { throw new ArgumentNullException("rhs"); } if (rhs.Dimension != dimension) { throw new DimensionMismatchException(); } // accuracy and iteration limits are very huristic, revisit later double accuracyGoal = Global.Accuracy * 128.0; int iterationMax = 256 + dimension / 2; // we use the stabilized biconjugate gradient algorithm // choose an initial guess ColumnVector x = new ColumnVector(dimension); for (int i = 0; i < x.Dimension; i++) { x[i] = 1.0; } // RowVector rt = x.Transpose(); // r is the deviation vector that we are trying to drive to zero ColumnVector r = rhs - this * x; double rho0 = 1.0; double a = 1.0; double omega = 1.0; ColumnVector v = new ColumnVector(dimension); ColumnVector p = new ColumnVector(dimension); for (int i = 1; i < iterationMax; i++) { double rho1 = rt * r; double beta = (rho1 / rho0) * (a / omega); p = r + beta * (p - omega * v); v = this * p; a = rho1 / (rt * v); ColumnVector s = r - a * v; ColumnVector t = this * s; omega = (t.Transpose() * s) / (t.Transpose() * t); x = x + a * p + omega * s; r = s - omega * t; if (r.FrobeniusNorm() <= accuracyGoal * rhs.FrobeniusNorm()) { return(x); } // prepare for next iteration rho0 = rho1; } throw new NonconvergenceException(); }
public void PrincipalComponentAnalysis() { int D = 3; int N = 10; // construct a sample Random rng = new Random(1); MultivariateSample sample = new MultivariateSample(D); for (int i = 0; i < N; i++) { double x = 1.0 * rng.NextDouble() - 1.0; double y = 4.0 * rng.NextDouble() - 2.0; double z = 9.0 * rng.NextDouble() - 3.0; sample.Add(x, y, z); } // get its column means RowVector mu = new RowVector(D); for (int i = 0; i < D; i++) { mu[i] = sample.Column(i).Mean; } // get total variance double tVariance = GetTotalVariance(sample); Console.WriteLine(tVariance); // do a principal component analysis PrincipalComponentAnalysis pca = sample.PrincipalComponentAnalysis(); Assert.IsTrue(pca.Dimension == sample.Dimension); Assert.IsTrue(pca.Count == sample.Count); // check that the PCs behave as expected for (int i = 0; i < pca.Dimension; i++) { PrincipalComponent pc = pca.Component(i); Assert.IsTrue(pc.Index == i); Assert.IsTrue(TestUtilities.IsNearlyEqual(pc.Weight * pc.NormalizedVector(), pc.ScaledVector())); Assert.IsTrue((0.0 <= pc.VarianceFraction) && (pc.VarianceFraction <= 1.0)); if (i == 0) { Assert.IsTrue(pc.VarianceFraction == pc.CumulativeVarianceFraction); } else { PrincipalComponent ppc = pca.Component(i - 1); Assert.IsTrue(pc.VarianceFraction <= ppc.VarianceFraction); Assert.IsTrue(TestUtilities.IsNearlyEqual(ppc.CumulativeVarianceFraction + pc.VarianceFraction, pc.CumulativeVarianceFraction)); } } // express the sample in terms of principal components MultivariateSample csample = pca.TransformedSample(); // check that the explained variances are as claimed for (int rD = 1; rD <= D; rD++) { MultivariateSample rSample = new MultivariateSample(D); foreach (double[] cEntry in csample) { RowVector x = mu.Copy(); for (int i = 0; i < rD; i++) { PrincipalComponent pc = pca.Component(i); x += (cEntry[i] * pc.Weight) * pc.NormalizedVector(); } rSample.Add(x); } double rVariance = GetTotalVariance(rSample); Console.WriteLine("{0} {1}", rD, rVariance); Assert.IsTrue(TestUtilities.IsNearlyEqual(rVariance / tVariance, pca.Component(rD-1).CumulativeVarianceFraction)); } }
private void TeachNeuralNetwork(ImageRectangle[] rectangles, BackgroundWorker worker, DoWorkEventArgs doWorkEvent, bool test) { int N = n * m * 3; RectangularMatrix weightMatrix = new RectangularMatrix(N, p); Random rand = new Random(); for (int i = 0; i < N; i++) { for (int j = 0; j < p; j++) { weightMatrix[i, j] = rand.NextDouble() * 0.1; } } RectangularMatrix secondWeightMatrix = weightMatrix.Transpose(); double totalError = e + 1; int totalIterationNumber = 0; state = new CurrentState(); RowVector[] vectors = new RowVector[rectangles.Length]; for (int i = 0; i < rectangles.Length; i++) { vectors[i] = new RowVector(((ImageRectangle)rectangles.GetValue(i)).GetVector()); } while (totalError > e && totalIterationNumber < iterationNumber) { totalError = 0; for (int i = 0; i < rectangles.Length; i++) { RowVector xVector = vectors[i]; RowVector yVector = xVector * weightMatrix; RowVector xSecondVector = yVector * secondWeightMatrix; RowVector deltaXVector = xSecondVector - xVector; weightMatrix = weightMatrix - a * xVector.Transpose() * deltaXVector * secondWeightMatrix.Transpose(); secondWeightMatrix = secondWeightMatrix - a * yVector.Transpose() * deltaXVector; } for (int i = 0; i < rectangles.Length; i++) { RowVector xVector = vectors[i]; RowVector yVector = xVector * weightMatrix; RowVector xSecondVector = yVector * secondWeightMatrix; RowVector deltaXVector = xSecondVector - xVector; for (int j = 0; j < deltaXVector.ColumnCount; j++) { totalError += deltaXVector[0, j] * deltaXVector[0, j]; } } totalIterationNumber++; state.CurentError = totalError; state.IterationNumber = totalIterationNumber; if (!test) { worker.ReportProgress(0, state); if (worker.CancellationPending) { doWorkEvent.Cancel = true; break; } } } for (int i = 0; i < rectangles.Length; i++) { RowVector xVector = vectors[i]; RowVector yVector = xVector * weightMatrix; RowVector xSecondVector = yVector * secondWeightMatrix; ((ImageRectangle)rectangles.GetValue(i)).SetPixelMatrixFromVector(xSecondVector.ToArray()); } state.Compressing = CalculateCompressing(rectangles.Length, N); state.FirstWeightMatrix = GetMatrixString(weightMatrix); state.SecondWeightMatrix = GetMatrixString(secondWeightMatrix); }
public void RectangularMatrixAccess() { // create a matrix via outer product ColumnVector cv = new ColumnVector(new double[] { 1, 2 }); RowVector rv = new RowVector(new double[] { 3, 4, 5 }); RectangularMatrix M = cv * rv; // check dimensions Assert.IsTrue(M.RowCount == cv.Dimension); Assert.IsTrue(M.ColumnCount == rv.Dimension); // check values for (int r = 0; r < M.RowCount; r++) { for (int c = 0; c < M.ColumnCount; c++) { Assert.IsTrue(M[r, c] == cv[r] * rv[c]); } } // extract a column ColumnVector mc = M.Column(1); Assert.IsTrue(mc.Dimension == M.RowCount); for (int i = 0; i < mc.Dimension; i++) { Assert.IsTrue(mc[i] == M[i, 1]); } // extract a row RowVector mr = M.Row(1); Assert.IsTrue(mr.Dimension == M.ColumnCount); for (int i = 0; i < mr.Dimension; i++) { Assert.IsTrue(mr[i] == M[1, i]); } // test clone RectangularMatrix MC = M.Copy(); Assert.IsTrue(MC.RowCount == M.RowCount); Assert.IsTrue(MC.ColumnCount == M.ColumnCount); // test equality of clone Assert.IsTrue(MC == M); Assert.IsFalse(MC != M); // test independence of clone MC[0, 0] += 1.0; Assert.IsFalse(MC == M); Assert.IsTrue(MC != M); }
private Image RecognizeImage(Image image) { int[] vector = image.ToVector(); RowVector X = new RowVector(vector.Length); for (int i = 0; i < X.ColumnCount; i++) { X[i] = vector[i]; } ColumnVector sMatrix = W * X.Transpose(); int[] Y = new int[sMatrix.RowCount]; for (int i = 0; i < Y.Length; i++) { Y[i] = sMatrix[i] > 0 ? 1 : -1; } return Image.GetImage(Y, image.Width, image.Height); }
public void Learn(BackgroundWorker backgroundWorker, DoWorkEventArgs e, double[] sequence, bool? showIteration) { ColumnVector[] learningMatrix = createLearningMatrix(sequence); double[] etalons = createEtalons(sequence); backgroundResult = new BackgroundResult(); backgroundResult.IsComplete = false; double totalError; int iterations = 0; do { // learn for (int i = 0; i < learningMatrix.Length; i++) { ColumnVector X = ConcatVertically(learningMatrix[i], contextNeurons); ColumnVector Xn = Normalize(X); double norm = X.FrobeniusNorm(); ColumnVector Y1 = weightMatrix1 * Xn; double Y2 = weightMatrix2 * Y1; double gamma2 = (Y2 * norm) - etalons[i]; RowVector gamma1 = gamma2 * weightMatrix2; RowVector a = learningCoefficient * gamma1; RectangularMatrix b = Xn * a; weightMatrix1 = weightMatrix1 - b.Transpose(); weightMatrix2 = weightMatrix2 - ((gamma2 * learningCoefficient) * Y1).Transpose(); contextNeurons = Y1; } totalError = 0; // calculate total error for (int i = 0; i < learningMatrix.Length; i++) { ColumnVector X = ConcatVertically(learningMatrix[i], contextNeurons); ColumnVector Xn = Normalize(X); double norm = X.FrobeniusNorm(); ColumnVector Y1 = weightMatrix1 * Xn; double Y2 = weightMatrix2 * Y1; double gamma2 = Y2 * norm - etalons[i]; totalError += Math.Pow(gamma2, 2); } backgroundResult.IterationNumber = iterations; backgroundResult.Error = totalError; backgroundResult.IsComplete = false; if (showIteration.Equals(true)) { backgroundWorker.ReportProgress(0, backgroundResult); Thread.Sleep(200); if (backgroundWorker.CancellationPending) { e.Cancel = true; break; } } iterations++; } while (totalError >= maxError && iterations <= maxIterations); backgroundResult.IterationNumber = iterations; backgroundResult.Error = totalError; backgroundResult.IsComplete = true; backgroundWorker.ReportProgress(0, backgroundResult); }
/// <summary> /// Multiplies a sparse matrix by a row vector. /// </summary> /// <param name="A">The matrix.</param> /// <param name="v">The row vector.</param> /// <returns>The product row vector.</returns> public static RowVector operator *(RowVector v, SparseSquareMatrix A) { if (v == null) throw new ArgumentNullException("v"); if (A == null) throw new ArgumentNullException("A"); if (v.Dimension != A.Dimension) throw new DimensionMismatchException(); RowVector vA = new RowVector(A.Dimension); for (int i = 0; i < A.Dimension; i++) { SparseMatrixElement element = A.columns[i]; while (element != null) { vA[i] += element.Value * v[element.Row]; element = element.NextInColumn; } } return (vA); }