From f1cf3de0f239f83e670ff07e0abee0a0cc49ff20 Mon Sep 17 00:00:00 2001 From: lidapeng Date: Wed, 5 Feb 2020 10:17:34 +0800 Subject: [PATCH] =?UTF-8?q?=E7=89=B9=E5=BE=81=E5=90=91=E9=87=8F=E9=87=8F?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/compiler.xml | 2 +- .idea/uiDesigner.xml | 124 +++++++++++++++++ .../java/org/wlld/MatrixTools/Matrix.java | 25 ++++ .../org/wlld/MatrixTools/MatrixOperation.java | 28 ++++ .../org/wlld/imageRecognition/Operation.java | 2 +- .../imageRecognition/border/KClustering.java | 131 ++++++++++++++++++ .../org/wlld/imageRecognition/border/LVQ.java | 108 +++++++++++++++ .../imageRecognition/border/MatrixBody.java | 29 ++++ src/test/java/org/wlld/HelloWorld.java | 10 +- 9 files changed, 452 insertions(+), 7 deletions(-) create mode 100644 .idea/uiDesigner.xml create mode 100644 src/main/java/org/wlld/imageRecognition/border/KClustering.java create mode 100644 src/main/java/org/wlld/imageRecognition/border/LVQ.java create mode 100644 src/main/java/org/wlld/imageRecognition/border/MatrixBody.java diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 6aa88ff..d280c68 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -6,8 +6,8 @@ - + diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..e96534f --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/org/wlld/MatrixTools/Matrix.java b/src/main/java/org/wlld/MatrixTools/Matrix.java index cf2313f..8762464 100644 --- a/src/main/java/org/wlld/MatrixTools/Matrix.java +++ b/src/main/java/org/wlld/MatrixTools/Matrix.java @@ -9,6 +9,9 @@ public class Matrix { private double[][] matrix;//矩阵本体 private int x;//矩阵的行数 private int y;//矩阵的列数 + private boolean isRowVector = false; + private boolean isVector = false;//是否是向量 + private boolean isZero = false;//是否是零矩阵 public int getX() {//获取行数 return x; @@ -22,6 +25,28 @@ public class Matrix { matrix = new double[x][y]; this.x = x; this.y = y; + if (x == 1 && y == 1) { + isZero = true; + } else if (x == 1 || y == 1) { + isVector = true; + if (x == 1) { + isRowVector = true; + } else { + isRowVector = false; + } + } + } + + public boolean isRowVector() { + return isRowVector; + } + + public boolean isVector() { + return isVector; + } + + public boolean isZero() { + return isZero; } public void clear() {//清除数据 diff --git a/src/main/java/org/wlld/MatrixTools/MatrixOperation.java b/src/main/java/org/wlld/MatrixTools/MatrixOperation.java index c7e2b54..6ac1755 100644 --- a/src/main/java/org/wlld/MatrixTools/MatrixOperation.java +++ b/src/main/java/org/wlld/MatrixTools/MatrixOperation.java @@ -23,6 +23,23 @@ public class MatrixOperation { } } + //矩阵相减 + public static Matrix sub(Matrix matrix1, Matrix matrix2) throws Exception {//矩阵相加 + if (matrix1.getX() == matrix2.getX() && matrix1.getY() == matrix2.getY()) { + Matrix matrix = new Matrix(matrix1.getX(), matrix1.getY()); + int x = matrix1.getX(); + int y = matrix1.getY(); + for (int i = 0; i < x; i++) {//遍历行 + for (int j = 0; j < y; j++) {//遍历列 + matrix.setNub(i, j, ArithUtil.sub(matrix1.getNumber(i, j), matrix2.getNumber(i, j))); + } + } + return matrix; + } else { + throw new Exception("matrix is not equals"); + } + } + //多元线性回归 public static Matrix getLinearRegression(Matrix parameter, Matrix Out) throws Exception { //将参数矩阵转置 @@ -37,6 +54,17 @@ public class MatrixOperation { return mulMatrix(matrix4, Out); } + //返回两个向量之间的欧氏距离的平方 + public static double getEDist(Matrix matrix1, Matrix matrix2) throws Exception { + if (matrix1.isRowVector() && matrix2.isRowVector() && matrix1.getY() == matrix2.getY()) { + mathMul(matrix2, -1); + Matrix matrix = add(matrix1, matrix2); + return getNorm(matrix); + } else { + throw new Exception("this matrix is not rowVector or length different"); + } + } + public static Matrix pushVector(Matrix myMatrix, Matrix matrix, boolean addRow) throws Exception { //向一个矩阵里合并一个行向量或者列向量到矩阵行或者列的末尾 if (matrix.getX() == 1 || matrix.getY() == 1) { diff --git a/src/main/java/org/wlld/imageRecognition/Operation.java b/src/main/java/org/wlld/imageRecognition/Operation.java index 7e460d7..c61cb3c 100644 --- a/src/main/java/org/wlld/imageRecognition/Operation.java +++ b/src/main/java/org/wlld/imageRecognition/Operation.java @@ -203,7 +203,7 @@ public class Operation {//进行计算 Matrix yw = borderBody.getyW(); Matrix hw = borderBody.gethW(); Matrix ww = borderBody.getwW(); - //将矩阵化为横向量 + //将矩阵化为向量 matrix = MatrixOperation.matrixToVector(matrix, true); //最后加一层池化 matrix = MatrixOperation.getPoolVector(matrix); diff --git a/src/main/java/org/wlld/imageRecognition/border/KClustering.java b/src/main/java/org/wlld/imageRecognition/border/KClustering.java new file mode 100644 index 0000000..8dcab79 --- /dev/null +++ b/src/main/java/org/wlld/imageRecognition/border/KClustering.java @@ -0,0 +1,131 @@ +package org.wlld.imageRecognition.border; + +import org.wlld.MatrixTools.Matrix; +import org.wlld.MatrixTools.MatrixOperation; +import org.wlld.tools.ArithUtil; + +import java.util.*; + +/** + * @author lidapeng + * @description //k均值聚类工具 + * @date 10:14 上午 2020/2/4 + */ +public class KClustering { + private List matrixList = new ArrayList<>();//聚类集合 + private int length;//向量长度 + private int speciesQuantity;//种类数量 + private Matrix[] matrices = new Matrix[speciesQuantity];//均值K + private Map> clusterMap = new HashMap<>();//簇 + + public Matrix[] getMatrices() { + return matrices; + } + + public Map> getClusterMap() { + return clusterMap; + } + + public KClustering(int speciesQuantity) { + this.speciesQuantity = speciesQuantity; + for (int i = 0; i < speciesQuantity; i++) { + clusterMap.put(i, new ArrayList<>()); + } + } + + public void setMatrixList(MatrixBody matrixBody) throws Exception { + if (matrixBody.getMatrix().isVector() && matrixBody.getMatrix().isRowVector()) { + Matrix matrix = matrixBody.getMatrix(); + if (matrixList.size() == 0) { + matrixList.add(matrixBody); + length = matrix.getY(); + } else { + if (length == matrix.getY()) { + matrixList.add(matrixBody); + } else { + throw new Exception("vector length is different"); + } + } + } else { + throw new Exception("this matrix is not vector or rowVector"); + } + } + + private Matrix[] averageMatrix() throws Exception { + Matrix[] matrices2 = new Matrix[speciesQuantity];//待比较均值K + for (MatrixBody matrixBody : matrixList) {//遍历当前集合 + Matrix matrix = matrixBody.getMatrix(); + double min = 0; + int id = 0; + for (int i = 0; i < matrices.length; i++) { + double dist = MatrixOperation.getEDist(matrix, matrices[i]); + if (min == 0 || dist < min) { + min = dist; + id = i; + } + } + List matrixList1 = clusterMap.get(id); + matrixList1.add(matrixBody); + } + //重新计算均值 + for (Map.Entry> entry : clusterMap.entrySet()) { + Matrix matrix = average(entry.getValue()); + matrices2[entry.getKey()] = matrix; + } + return matrices2; + } + + private void clear() { + for (Map.Entry> entry : clusterMap.entrySet()) { + entry.getValue().clear(); + } + } + + private Matrix average(List matrixList) throws Exception {//进行矩阵均值计算 + double nub = ArithUtil.div(1, matrixList.size()); + Matrix matrix = new Matrix(0, length); + for (MatrixBody matrixBody1 : matrixList) { + matrix = MatrixOperation.add(matrix, matrixBody1.getMatrix()); + } + MatrixOperation.mathMul(matrix, nub); + return matrix; + } + + public void start() throws Exception {//开始聚类 + if (matrixList.size() > 1) { + Random random = new Random(); + for (int i = 0; i < matrices.length; i++) {//初始化均值向量 + int index = random.nextInt(matrixList.size()); + matrices[i] = matrixList.get(index).getMatrix(); + } + //进行两者的比较 + boolean isEqual = false; + do { + Matrix[] matrices2 = averageMatrix(); + isEqual = equals(matrices, matrices2); + if (!isEqual) { + matrices = matrices2; + clear(); + } + } + while (isEqual); + } else { + throw new Exception("matrixList number less than 2"); + } + } + + public boolean equals(Matrix[] matrices1, Matrix[] matrices2) throws Exception { + boolean isEquals = true; + for (int i = 0; i < matrices1.length; i++) { + Matrix matrix1 = matrices1[i]; + Matrix matrix2 = matrices2[i]; + for (int j = 0; j < length; j++) { + if (matrix1.getNumber(0, j) != matrix2.getNumber(0, j)) { + isEquals = false; + break; + } + } + } + return isEquals; + } +} diff --git a/src/main/java/org/wlld/imageRecognition/border/LVQ.java b/src/main/java/org/wlld/imageRecognition/border/LVQ.java new file mode 100644 index 0000000..05f4931 --- /dev/null +++ b/src/main/java/org/wlld/imageRecognition/border/LVQ.java @@ -0,0 +1,108 @@ +package org.wlld.imageRecognition.border; + +import org.wlld.MatrixTools.Matrix; +import org.wlld.MatrixTools.MatrixOperation; +import org.wlld.tools.ArithUtil; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +/** + * @author lidapeng + * @description LVQ 向量量化 + * @date 5:36 下午 2020/2/4 + */ +public class LVQ { + private int typeNub;//原型聚类个数,即分类个数 + private MatrixBody[] model = new MatrixBody[typeNub];//原型向量 + private List matrixList = new ArrayList<>(); + private double studyPoint = 0.1;//量化学习率 + private int length;//向量长度 + + public LVQ(int typeNub) { + this.typeNub = typeNub; + } + + public MatrixBody[] getModel() { + return model; + } + + public void insertMatrixBody(MatrixBody matrixBody) throws Exception { + if (matrixBody.getMatrix().isVector() && matrixBody.getMatrix().isRowVector()) { + Matrix matrix = matrixBody.getMatrix(); + if (matrixList.size() == 0) { + matrixList.add(matrixBody); + length = matrix.getY(); + } else { + if (length == matrix.getY()) { + matrixList.add(matrixBody); + } else { + throw new Exception("vector length is different"); + } + } + } else { + throw new Exception("this matrix is not vector or rowVector"); + } + } + + private double study() throws Exception { + double error = 0; + for (MatrixBody matrixBody : matrixList) { + Matrix matrix = matrixBody.getMatrix();//特征向量 + long type = matrixBody.getId();//类别 + for (int i = 0; i < typeNub; i++) { + MatrixBody modelBody = model[i]; + Matrix modelMatrix = modelBody.getMatrix(); + long id = modelBody.getId(); + boolean isRight = id == type;//类别是否相同 + //对矩阵进行修正 + Matrix matrix1 = op(matrix, modelMatrix, isRight); + //修正矩阵与原矩阵的范数差 + double dist = vectorEqual(modelMatrix, matrix1); + //将修正后的向量进行赋值 + modelBody.setMatrix(matrix1); + //统计变化值 + error = ArithUtil.add(error, dist); + } + } + return error; + } + + //比较两个向量之间的范数差 + private double vectorEqual(Matrix matrix1, Matrix matrix2) throws Exception { + Matrix matrix = MatrixOperation.sub(matrix1, matrix2); + return MatrixOperation.getNorm(matrix); + } + + private Matrix op(Matrix matrix, Matrix modelMatrix, boolean isRight) throws Exception { + Matrix matrix1 = MatrixOperation.sub(matrix, modelMatrix); + MatrixOperation.mathMul(matrix1, studyPoint); + Matrix matrix2; + if (isRight) { + matrix2 = MatrixOperation.add(modelMatrix, matrix1); + } else { + matrix2 = MatrixOperation.sub(modelMatrix, matrix1); + } + return matrix2; + } + + public void start() throws Exception {//开始向量量化聚类 + Random random = new Random(); + for (int i = 0; i < typeNub; i++) { + MatrixBody matrixBody = new MatrixBody(); + Matrix matrix = new Matrix(1, length); + matrixBody.setMatrix(matrix); + matrixBody.setId(i); + for (int j = 0; j < length; j++) { + matrix.setNub(0, j, random.nextInt(10)); + } + model[i] = matrixBody; + } + //初始化完成 + for (int k = 0; k < 1000; k++) { + double error = study(); + System.out.println("error==" + error); + } + } +} diff --git a/src/main/java/org/wlld/imageRecognition/border/MatrixBody.java b/src/main/java/org/wlld/imageRecognition/border/MatrixBody.java new file mode 100644 index 0000000..ebce5ce --- /dev/null +++ b/src/main/java/org/wlld/imageRecognition/border/MatrixBody.java @@ -0,0 +1,29 @@ +package org.wlld.imageRecognition.border; + +import org.wlld.MatrixTools.Matrix; + +/** + * @author lidapeng + * @description + * @date 3:33 下午 2020/2/4 + */ +public class MatrixBody {//给矩阵绑定一个id + private int id;//唯一ID + private Matrix matrix;//矩阵 + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public Matrix getMatrix() { + return matrix; + } + + public void setMatrix(Matrix matrix) { + this.matrix = matrix; + } +} diff --git a/src/test/java/org/wlld/HelloWorld.java b/src/test/java/org/wlld/HelloWorld.java index 7c0ae07..085a649 100644 --- a/src/test/java/org/wlld/HelloWorld.java +++ b/src/test/java/org/wlld/HelloWorld.java @@ -41,7 +41,7 @@ public class HelloWorld { templeConfig.init(StudyPattern.Accuracy_Pattern, true, 3204, 4032, 1); templeConfig.insertModel(modelParameter); Operation operation = new Operation(templeConfig); - for (int i = 1; i < 300; i++) {//faster rcnn神经网络学习 + for (int i = 1; i < 20; i++) {//faster rcnn神经网络学习 System.out.println("study==" + i); //读取本地URL地址图片,并转化成矩阵 Matrix right = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/c/c" + i + ".png"); @@ -53,10 +53,10 @@ public class HelloWorld { } templeConfig.boxStudy();//边框回归 templeConfig.clustering();//进行聚类 - ModelParameter modelParameter1 = templeConfig.getModel(); - String a = JSON.toJSONString(modelParameter1); - System.out.println(a); - for (int j = 121; j < 140; j++) { +// ModelParameter modelParameter1 = templeConfig.getModel(); +// String a = JSON.toJSONString(modelParameter1); +// System.out.println(a); + for (int j = 1; j < 2; j++) { Matrix right = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/c/c" + j + ".png"); Map> map = operation.lookWithPosition(right, j); System.out.println("j===" + j);