26 changed files with 2043 additions and 14 deletions
@ -0,0 +1,38 @@ |
|||||||
|
-- 2024-05-07 维修表缺少字段 |
||||||
|
ALTER TABLE maintain_info ADD cost numeric(2,0) NULL; |
||||||
|
EXEC sys.sp_addextendedproperty 'MS_Description', N'材料费用', 'schema', N'dbo', 'table', N'maintain_info', 'column', N'cost'; |
||||||
|
ALTER TABLE maintain_info ADD contents varchar(100) NULL; |
||||||
|
EXEC sys.sp_addextendedproperty 'MS_Description', N'维保内容', 'schema', N'dbo', 'table', N'maintain_info', 'column', N'contents'; |
||||||
|
ALTER TABLE maintain_info ADD evaluate varchar(10) NULL; |
||||||
|
EXEC sys.sp_addextendedproperty 'MS_Description', N'评价内容', 'schema', N'dbo', 'table', N'maintain_info', 'column', N'evaluate'; |
||||||
|
|
||||||
|
-- 训练集合: |
||||||
|
select |
||||||
|
eds.cur_date, |
||||||
|
eds.building_id, |
||||||
|
isnull(eds.water_value, |
||||||
|
0) as water_value, |
||||||
|
isnull(eds.elect_value, |
||||||
|
0) as elect_value, |
||||||
|
isnull(convert(numeric(24,2),t1.water_level), |
||||||
|
0) as water_level |
||||||
|
from |
||||||
|
energy_day_sum eds |
||||||
|
left join ( |
||||||
|
select |
||||||
|
convert(date, |
||||||
|
cur_date) as cur_date, |
||||||
|
building_id, |
||||||
|
avg(isnull(convert(numeric(24, 2), water_level), 0)) as water_level |
||||||
|
from |
||||||
|
history_data |
||||||
|
group by |
||||||
|
convert(date, |
||||||
|
cur_date), |
||||||
|
building_id |
||||||
|
) t1 on |
||||||
|
eds.cur_date = t1.cur_date and eds.building_id = t1.building_id |
||||||
|
where eds.building_id != '所有' |
||||||
|
order by |
||||||
|
eds.building_id, |
||||||
|
eds.cur_date |
@ -0,0 +1,135 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||||
|
<parent> |
||||||
|
<groupId>com.mh</groupId> |
||||||
|
<artifactId>chws</artifactId> |
||||||
|
<version>1.0-SNAPSHOT</version> |
||||||
|
</parent> |
||||||
|
<modelVersion>4.0.0</modelVersion> |
||||||
|
|
||||||
|
<groupId>com.mh</groupId> |
||||||
|
<artifactId>algorithm</artifactId> |
||||||
|
<version>1.0.0</version> |
||||||
|
<packaging>jar</packaging> |
||||||
|
|
||||||
|
<properties> |
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
||||||
|
<encoding>UTF-8</encoding> |
||||||
|
<java.version>1.8</java.version> |
||||||
|
<maven.compiler.source>1.8</maven.compiler.source> |
||||||
|
<maven.compiler.target>1.8</maven.compiler.target> |
||||||
|
</properties> |
||||||
|
<dependencies> |
||||||
|
<!-- https://mvnrepository.com/artifact/net.sourceforge.javacsv/javacsv --> |
||||||
|
<dependency> |
||||||
|
<groupId>net.sourceforge.javacsv</groupId> |
||||||
|
<artifactId>javacsv</artifactId> |
||||||
|
<version>2.0</version> |
||||||
|
</dependency> |
||||||
|
<dependency> |
||||||
|
<groupId>gov.nist.math</groupId> |
||||||
|
<artifactId>jama</artifactId> |
||||||
|
<version>1.0.3</version> |
||||||
|
</dependency> |
||||||
|
<dependency> |
||||||
|
<groupId>junit</groupId> |
||||||
|
<artifactId>junit</artifactId> |
||||||
|
<version>RELEASE</version> |
||||||
|
<scope>test</scope> |
||||||
|
</dependency> |
||||||
|
</dependencies> |
||||||
|
|
||||||
|
<build> |
||||||
|
<plugins> |
||||||
|
<plugin> |
||||||
|
<groupId>org.apache.maven.plugins</groupId> |
||||||
|
<artifactId>maven-compiler-plugin</artifactId> |
||||||
|
<version>3.1</version> |
||||||
|
<configuration> |
||||||
|
<source>1.8</source> |
||||||
|
<target>1.8</target> |
||||||
|
</configuration> |
||||||
|
</plugin> |
||||||
|
</plugins> |
||||||
|
</build> |
||||||
|
|
||||||
|
<profiles> |
||||||
|
<profile> |
||||||
|
<id>default</id> |
||||||
|
<activation> |
||||||
|
<activeByDefault>true</activeByDefault> |
||||||
|
</activation> |
||||||
|
<build> |
||||||
|
<plugins> |
||||||
|
<!-- java版本 --> |
||||||
|
<plugin> |
||||||
|
<groupId>org.apache.maven.plugins</groupId> |
||||||
|
<artifactId>maven-compiler-plugin</artifactId> |
||||||
|
<version>3.8.0</version> |
||||||
|
<configuration> |
||||||
|
<source>1.8</source> |
||||||
|
<target>1.8</target> |
||||||
|
<encoding>UTF-8</encoding> |
||||||
|
</configuration> |
||||||
|
</plugin> |
||||||
|
<!-- 这是javadoc打包插件 --> |
||||||
|
<plugin> |
||||||
|
<groupId>org.apache.maven.plugins</groupId> |
||||||
|
<artifactId>maven-javadoc-plugin</artifactId> |
||||||
|
<version>2.9.1</version> |
||||||
|
<executions> |
||||||
|
<execution> |
||||||
|
<id>attach-javadocs</id> |
||||||
|
<goals> |
||||||
|
<goal>jar</goal> |
||||||
|
</goals> |
||||||
|
<!-- 该处屏蔽jdk1.8后javadoc的严格校验 --> |
||||||
|
<configuration> |
||||||
|
<additionalparam>-Xdoclint:none</additionalparam> |
||||||
|
</configuration> |
||||||
|
</execution> |
||||||
|
</executions> |
||||||
|
</plugin> |
||||||
|
<!-- 打包源码插件 --> |
||||||
|
<plugin> |
||||||
|
<groupId>org.apache.maven.plugins</groupId> |
||||||
|
<artifactId>maven-source-plugin</artifactId> |
||||||
|
<version>2.3</version> |
||||||
|
<executions> |
||||||
|
<execution> |
||||||
|
<id>attach-sources</id> |
||||||
|
<goals> |
||||||
|
<goal>jar</goal> |
||||||
|
</goals> |
||||||
|
</execution> |
||||||
|
</executions> |
||||||
|
</plugin> |
||||||
|
<!--签名插件--> |
||||||
|
<plugin> |
||||||
|
<groupId>org.apache.maven.plugins</groupId> |
||||||
|
<artifactId>maven-gpg-plugin</artifactId> |
||||||
|
<version>1.4</version> |
||||||
|
<executions> |
||||||
|
<execution> |
||||||
|
<id>sign-artifacts</id> |
||||||
|
<phase>verify</phase> |
||||||
|
<goals> |
||||||
|
<goal>sign</goal> |
||||||
|
</goals> |
||||||
|
</execution> |
||||||
|
</executions> |
||||||
|
</plugin> |
||||||
|
<plugin> |
||||||
|
<artifactId>maven-jar-plugin</artifactId> |
||||||
|
<version>2.3.1</version> |
||||||
|
<configuration> |
||||||
|
<classesDirectory>target/classes</classesDirectory> |
||||||
|
</configuration> |
||||||
|
</plugin> |
||||||
|
</plugins> |
||||||
|
</build> |
||||||
|
</profile> |
||||||
|
</profiles> |
||||||
|
</project> |
@ -0,0 +1,8 @@ |
|||||||
|
package com.mh.algorithm.bpnn; |
||||||
|
|
||||||
|
public interface ActivationFunction { |
||||||
|
//计算值
|
||||||
|
double computeValue(double val); |
||||||
|
//计算导数
|
||||||
|
double computeDerivative(double val); |
||||||
|
} |
@ -0,0 +1,111 @@ |
|||||||
|
package com.mh.algorithm.bpnn; |
||||||
|
|
||||||
|
import com.mh.algorithm.matrix.Matrix; |
||||||
|
|
||||||
|
import java.io.Serializable; |
||||||
|
|
||||||
|
public class BPModel implements Serializable { |
||||||
|
//BP神经网络权值与阈值
|
||||||
|
private Matrix weightIJ; |
||||||
|
private Matrix b1; |
||||||
|
private Matrix weightJP; |
||||||
|
private Matrix b2; |
||||||
|
/*用于反归一化*/ |
||||||
|
private Matrix inputMax; |
||||||
|
private Matrix inputMin; |
||||||
|
private Matrix outputMax; |
||||||
|
private Matrix outputMin; |
||||||
|
/*BP神经网络训练参数*/ |
||||||
|
private BPParameter bpParameter; |
||||||
|
/*BP神经网络训练情况*/ |
||||||
|
private double error; |
||||||
|
private int times; |
||||||
|
|
||||||
|
public Matrix getWeightIJ() { |
||||||
|
return weightIJ; |
||||||
|
} |
||||||
|
|
||||||
|
public void setWeightIJ(Matrix weightIJ) { |
||||||
|
this.weightIJ = weightIJ; |
||||||
|
} |
||||||
|
|
||||||
|
public Matrix getB1() { |
||||||
|
return b1; |
||||||
|
} |
||||||
|
|
||||||
|
public void setB1(Matrix b1) { |
||||||
|
this.b1 = b1; |
||||||
|
} |
||||||
|
|
||||||
|
public Matrix getWeightJP() { |
||||||
|
return weightJP; |
||||||
|
} |
||||||
|
|
||||||
|
public void setWeightJP(Matrix weightJP) { |
||||||
|
this.weightJP = weightJP; |
||||||
|
} |
||||||
|
|
||||||
|
public Matrix getB2() { |
||||||
|
return b2; |
||||||
|
} |
||||||
|
|
||||||
|
public void setB2(Matrix b2) { |
||||||
|
this.b2 = b2; |
||||||
|
} |
||||||
|
|
||||||
|
public Matrix getInputMax() { |
||||||
|
return inputMax; |
||||||
|
} |
||||||
|
|
||||||
|
public void setInputMax(Matrix inputMax) { |
||||||
|
this.inputMax = inputMax; |
||||||
|
} |
||||||
|
|
||||||
|
public Matrix getInputMin() { |
||||||
|
return inputMin; |
||||||
|
} |
||||||
|
|
||||||
|
public void setInputMin(Matrix inputMin) { |
||||||
|
this.inputMin = inputMin; |
||||||
|
} |
||||||
|
|
||||||
|
public Matrix getOutputMax() { |
||||||
|
return outputMax; |
||||||
|
} |
||||||
|
|
||||||
|
public void setOutputMax(Matrix outputMax) { |
||||||
|
this.outputMax = outputMax; |
||||||
|
} |
||||||
|
|
||||||
|
public Matrix getOutputMin() { |
||||||
|
return outputMin; |
||||||
|
} |
||||||
|
|
||||||
|
public void setOutputMin(Matrix outputMin) { |
||||||
|
this.outputMin = outputMin; |
||||||
|
} |
||||||
|
|
||||||
|
public BPParameter getBpParameter() { |
||||||
|
return bpParameter; |
||||||
|
} |
||||||
|
|
||||||
|
public void setBpParameter(BPParameter bpParameter) { |
||||||
|
this.bpParameter = bpParameter; |
||||||
|
} |
||||||
|
|
||||||
|
public double getError() { |
||||||
|
return error; |
||||||
|
} |
||||||
|
|
||||||
|
public void setError(double error) { |
||||||
|
this.error = error; |
||||||
|
} |
||||||
|
|
||||||
|
public int getTimes() { |
||||||
|
return times; |
||||||
|
} |
||||||
|
|
||||||
|
public void setTimes(int times) { |
||||||
|
this.times = times; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,257 @@ |
|||||||
|
package com.mh.algorithm.bpnn; |
||||||
|
|
||||||
|
import com.mh.algorithm.matrix.Matrix; |
||||||
|
import com.mh.algorithm.utils.MatrixUtil; |
||||||
|
|
||||||
|
import java.util.*; |
||||||
|
|
||||||
|
public class BPNeuralNetworkFactory { |
||||||
|
/** |
||||||
|
* 训练BP神经网络模型 |
||||||
|
* @param bpParameter |
||||||
|
* @param inputAndOutput |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public BPModel trainBP(BPParameter bpParameter, Matrix inputAndOutput) throws Exception { |
||||||
|
|
||||||
|
ActivationFunction activationFunction = bpParameter.getActivationFunction(); |
||||||
|
int inputCount = bpParameter.getInputLayerNeuronCount(); |
||||||
|
int hiddenCount = bpParameter.getHiddenLayerNeuronCount(); |
||||||
|
int outputCount = bpParameter.getOutputLayerNeuronCount(); |
||||||
|
double normalizationMin = bpParameter.getNormalizationMin(); |
||||||
|
double normalizationMax = bpParameter.getNormalizationMax(); |
||||||
|
double step = bpParameter.getStep(); |
||||||
|
double momentumFactor = bpParameter.getMomentumFactor(); |
||||||
|
double precision = bpParameter.getPrecision(); |
||||||
|
int maxTimes = bpParameter.getMaxTimes(); |
||||||
|
|
||||||
|
if(inputAndOutput.getMatrixColCount() != inputCount + outputCount){ |
||||||
|
throw new Exception("神经元个数不符,请修改"); |
||||||
|
} |
||||||
|
// 初始化权值
|
||||||
|
Matrix weightIJ = initWeight(inputCount, hiddenCount); |
||||||
|
Matrix weightJP = initWeight(hiddenCount, outputCount); |
||||||
|
|
||||||
|
// 初始化阈值
|
||||||
|
Matrix b1 = initThreshold(hiddenCount); |
||||||
|
Matrix b2 = initThreshold(outputCount); |
||||||
|
|
||||||
|
// 动量项
|
||||||
|
Matrix deltaWeightIJ0 = new Matrix(inputCount, hiddenCount); |
||||||
|
Matrix deltaWeightJP0 = new Matrix(hiddenCount, outputCount); |
||||||
|
Matrix deltaB10 = new Matrix(1, hiddenCount); |
||||||
|
Matrix deltaB20 = new Matrix(1, outputCount); |
||||||
|
|
||||||
|
// 截取输入矩阵和输出矩阵
|
||||||
|
Matrix input = inputAndOutput.subMatrix(0,inputAndOutput.getMatrixRowCount(),0,inputCount); |
||||||
|
Matrix output = inputAndOutput.subMatrix(0,inputAndOutput.getMatrixRowCount(),inputCount,outputCount); |
||||||
|
|
||||||
|
// 归一化
|
||||||
|
Map<String,Object> inputAfterNormalize = MatrixUtil.normalize(input, normalizationMin, normalizationMax); |
||||||
|
input = (Matrix) inputAfterNormalize.get("res"); |
||||||
|
|
||||||
|
Map<String,Object> outputAfterNormalize = MatrixUtil.normalize(output, normalizationMin, normalizationMax); |
||||||
|
output = (Matrix) outputAfterNormalize.get("res"); |
||||||
|
|
||||||
|
int times = 1; |
||||||
|
double E = 0;//误差
|
||||||
|
while (times < maxTimes) { |
||||||
|
/*-----------------正向传播---------------------*/ |
||||||
|
// 隐含层输入
|
||||||
|
Matrix jIn = input.multiple(weightIJ); |
||||||
|
// 扩充阈值
|
||||||
|
Matrix b1Copy = b1.extend(2,jIn.getMatrixRowCount()); |
||||||
|
// 加上阈值
|
||||||
|
jIn = jIn.plus(b1Copy); |
||||||
|
// 隐含层输出
|
||||||
|
Matrix jOut = computeValue(jIn,activationFunction); |
||||||
|
// 输出层输入
|
||||||
|
Matrix pIn = jOut.multiple(weightJP); |
||||||
|
// 扩充阈值
|
||||||
|
Matrix b2Copy = b2.extend(2, pIn.getMatrixRowCount()); |
||||||
|
// 加上阈值
|
||||||
|
pIn = pIn.plus(b2Copy); |
||||||
|
// 输出层输出
|
||||||
|
Matrix pOut = computeValue(pIn,activationFunction); |
||||||
|
// 计算误差
|
||||||
|
Matrix e = output.subtract(pOut); |
||||||
|
E = computeE(e);//误差
|
||||||
|
// 判断是否符合精度
|
||||||
|
if (Math.abs(E) <= precision) { |
||||||
|
System.out.println("满足精度"); |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
/*-----------------反向传播---------------------*/ |
||||||
|
// J与P之间权值修正量
|
||||||
|
Matrix deltaWeightJP = e.multiple(step); |
||||||
|
deltaWeightJP = deltaWeightJP.pointMultiple(computeDerivative(pIn,activationFunction)); |
||||||
|
deltaWeightJP = deltaWeightJP.transpose().multiple(jOut); |
||||||
|
deltaWeightJP = deltaWeightJP.transpose(); |
||||||
|
// P层神经元阈值修正量
|
||||||
|
Matrix deltaThresholdP = e.multiple(step); |
||||||
|
deltaThresholdP = deltaThresholdP.transpose().multiple(computeDerivative(pIn, activationFunction)); |
||||||
|
|
||||||
|
// I与J之间的权值修正量
|
||||||
|
Matrix deltaO = e.pointMultiple(computeDerivative(pIn,activationFunction)); |
||||||
|
Matrix tmp = weightJP.multiple(deltaO.transpose()).transpose(); |
||||||
|
Matrix deltaWeightIJ = tmp.pointMultiple(computeDerivative(jIn, activationFunction)); |
||||||
|
deltaWeightIJ = input.transpose().multiple(deltaWeightIJ); |
||||||
|
deltaWeightIJ = deltaWeightIJ.multiple(step); |
||||||
|
|
||||||
|
// J层神经元阈值修正量
|
||||||
|
Matrix deltaThresholdJ = tmp.transpose().multiple(computeDerivative(jIn, activationFunction)); |
||||||
|
deltaThresholdJ = deltaThresholdJ.multiple(-step); |
||||||
|
|
||||||
|
if (times == 1) { |
||||||
|
// 更新权值与阈值
|
||||||
|
weightIJ = weightIJ.plus(deltaWeightIJ); |
||||||
|
weightJP = weightJP.plus(deltaWeightJP); |
||||||
|
b1 = b1.plus(deltaThresholdJ); |
||||||
|
b2 = b2.plus(deltaThresholdP); |
||||||
|
}else{ |
||||||
|
// 加动量项
|
||||||
|
weightIJ = weightIJ.plus(deltaWeightIJ).plus(deltaWeightIJ0.multiple(momentumFactor)); |
||||||
|
weightJP = weightJP.plus(deltaWeightJP).plus(deltaWeightJP0.multiple(momentumFactor)); |
||||||
|
b1 = b1.plus(deltaThresholdJ).plus(deltaB10.multiple(momentumFactor)); |
||||||
|
b2 = b2.plus(deltaThresholdP).plus(deltaB20.multiple(momentumFactor)); |
||||||
|
} |
||||||
|
|
||||||
|
deltaWeightIJ0 = deltaWeightIJ; |
||||||
|
deltaWeightJP0 = deltaWeightJP; |
||||||
|
deltaB10 = deltaThresholdJ; |
||||||
|
deltaB20 = deltaThresholdP; |
||||||
|
|
||||||
|
times++; |
||||||
|
} |
||||||
|
|
||||||
|
// BP神经网络的输出
|
||||||
|
BPModel result = new BPModel(); |
||||||
|
result.setInputMax((Matrix) inputAfterNormalize.get("max")); |
||||||
|
result.setInputMin((Matrix) inputAfterNormalize.get("min")); |
||||||
|
result.setOutputMax((Matrix) outputAfterNormalize.get("max")); |
||||||
|
result.setOutputMin((Matrix) outputAfterNormalize.get("min")); |
||||||
|
result.setWeightIJ(weightIJ); |
||||||
|
result.setWeightJP(weightJP); |
||||||
|
result.setB1(b1); |
||||||
|
result.setB2(b2); |
||||||
|
result.setError(E); |
||||||
|
result.setTimes(times); |
||||||
|
result.setBpParameter(bpParameter); |
||||||
|
System.out.println("循环次数:" + times + ",误差:" + E); |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 计算BP神经网络的值 |
||||||
|
* @param bpModel |
||||||
|
* @param input |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public Matrix computeBP(BPModel bpModel,Matrix input) throws Exception { |
||||||
|
if (input.getMatrixColCount() != bpModel.getBpParameter().getInputLayerNeuronCount()) { |
||||||
|
throw new Exception("输入矩阵纬度有误"); |
||||||
|
} |
||||||
|
ActivationFunction activationFunction = bpModel.getBpParameter().getActivationFunction(); |
||||||
|
Matrix weightIJ = bpModel.getWeightIJ(); |
||||||
|
Matrix weightJP = bpModel.getWeightJP(); |
||||||
|
Matrix b1 = bpModel.getB1(); |
||||||
|
Matrix b2 = bpModel.getB2(); |
||||||
|
double[][] normalizedInput = new double[input.getMatrixRowCount()][input.getMatrixColCount()]; |
||||||
|
for (int i = 0; i < input.getMatrixRowCount(); i++) { |
||||||
|
for (int j = 0; j < input.getMatrixColCount(); j++) { |
||||||
|
normalizedInput[i][j] = bpModel.getBpParameter().getNormalizationMin() |
||||||
|
+ (input.getValOfIdx(i,j) - bpModel.getInputMin().getValOfIdx(0,j)) |
||||||
|
/ (bpModel.getInputMax().getValOfIdx(0,j) - bpModel.getInputMin().getValOfIdx(0,j)) |
||||||
|
* (bpModel.getBpParameter().getNormalizationMax() - bpModel.getBpParameter().getNormalizationMin()); |
||||||
|
} |
||||||
|
} |
||||||
|
Matrix normalizedInputMatrix = new Matrix(normalizedInput); |
||||||
|
Matrix jIn = normalizedInputMatrix.multiple(weightIJ); |
||||||
|
// 扩充阈值
|
||||||
|
Matrix b1Copy = b1.extend(2,jIn.getMatrixRowCount()); |
||||||
|
// 加上阈值
|
||||||
|
jIn = jIn.plus(b1Copy); |
||||||
|
// 隐含层输出
|
||||||
|
Matrix jOut = computeValue(jIn,activationFunction); |
||||||
|
// 输出层输入
|
||||||
|
Matrix pIn = jOut.multiple(weightJP); |
||||||
|
// 扩充阈值
|
||||||
|
Matrix b2Copy = b2.extend(2,pIn.getMatrixRowCount()); |
||||||
|
// 加上阈值
|
||||||
|
pIn = pIn.plus(b2Copy); |
||||||
|
// 输出层输出
|
||||||
|
Matrix pOut = computeValue(pIn,activationFunction); |
||||||
|
// 反归一化
|
||||||
|
return MatrixUtil.inverseNormalize(pOut, bpModel.getBpParameter().getNormalizationMax(), bpModel.getBpParameter().getNormalizationMin(), bpModel.getOutputMax(), bpModel.getOutputMin()); |
||||||
|
} |
||||||
|
|
||||||
|
// 初始化权值
|
||||||
|
private Matrix initWeight(int x,int y){ |
||||||
|
Random random=new Random(); |
||||||
|
double[][] weight = new double[x][y]; |
||||||
|
for (int i = 0; i < x; i++) { |
||||||
|
for (int j = 0; j < y; j++) { |
||||||
|
weight[i][j] = 2*random.nextDouble()-1; |
||||||
|
} |
||||||
|
} |
||||||
|
return new Matrix(weight); |
||||||
|
} |
||||||
|
// 初始化阈值
|
||||||
|
private Matrix initThreshold(int x){ |
||||||
|
Random random = new Random(); |
||||||
|
double[][] result = new double[1][x]; |
||||||
|
for (int i = 0; i < x; i++) { |
||||||
|
result[0][i] = 2*random.nextDouble()-1; |
||||||
|
} |
||||||
|
return new Matrix(result); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 计算激活函数的值 |
||||||
|
* @param a |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private Matrix computeValue(Matrix a, ActivationFunction activationFunction) throws Exception { |
||||||
|
if (a.getMatrix() == null) { |
||||||
|
throw new Exception("参数值为空"); |
||||||
|
} |
||||||
|
double[][] result = new double[a.getMatrixRowCount()][a.getMatrixColCount()]; |
||||||
|
for (int i = 0; i < a.getMatrixRowCount(); i++) { |
||||||
|
for (int j = 0; j < a.getMatrixColCount(); j++) { |
||||||
|
result[i][j] = activationFunction.computeValue(a.getValOfIdx(i,j)); |
||||||
|
} |
||||||
|
} |
||||||
|
return new Matrix(result); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 激活函数导数的值 |
||||||
|
* @param a |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private Matrix computeDerivative(Matrix a , ActivationFunction activationFunction) throws Exception { |
||||||
|
if (a.getMatrix() == null) { |
||||||
|
throw new Exception("参数值为空"); |
||||||
|
} |
||||||
|
double[][] result = new double[a.getMatrixRowCount()][a.getMatrixColCount()]; |
||||||
|
for (int i = 0; i < a.getMatrixRowCount(); i++) { |
||||||
|
for (int j = 0; j < a.getMatrixColCount(); j++) { |
||||||
|
result[i][j] = activationFunction.computeDerivative(a.getValOfIdx(i,j)); |
||||||
|
} |
||||||
|
} |
||||||
|
return new Matrix(result); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 计算误差 |
||||||
|
* @param e |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private double computeE(Matrix e){ |
||||||
|
e = e.square(); |
||||||
|
return 0.5*e.sumAll(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,106 @@ |
|||||||
|
package com.mh.algorithm.bpnn; |
||||||
|
|
||||||
|
import java.io.Serializable; |
||||||
|
|
||||||
|
public class BPParameter implements Serializable { |
||||||
|
|
||||||
|
//输入层神经元个数
|
||||||
|
private int inputLayerNeuronCount = 3; |
||||||
|
//隐含层神经元个数
|
||||||
|
private int hiddenLayerNeuronCount = 3; |
||||||
|
//输出层神经元个数
|
||||||
|
private int outputLayerNeuronCount = 1; |
||||||
|
//归一化区间
|
||||||
|
private double normalizationMin = 0.2; |
||||||
|
private double normalizationMax = 0.8; |
||||||
|
//学习步长
|
||||||
|
private double step = 0.05; |
||||||
|
//动量因子
|
||||||
|
private double momentumFactor = 0.2; |
||||||
|
//激活函数
|
||||||
|
private ActivationFunction activationFunction = new Sigmoid(); |
||||||
|
//精度
|
||||||
|
private double precision = 0.000001; |
||||||
|
//最大循环次数
|
||||||
|
private int maxTimes = 1000000; |
||||||
|
|
||||||
|
public double getMomentumFactor() { |
||||||
|
return momentumFactor; |
||||||
|
} |
||||||
|
|
||||||
|
public void setMomentumFactor(double momentumFactor) { |
||||||
|
this.momentumFactor = momentumFactor; |
||||||
|
} |
||||||
|
|
||||||
|
public double getStep() { |
||||||
|
return step; |
||||||
|
} |
||||||
|
|
||||||
|
public void setStep(double step) { |
||||||
|
this.step = step; |
||||||
|
} |
||||||
|
|
||||||
|
public double getNormalizationMin() { |
||||||
|
return normalizationMin; |
||||||
|
} |
||||||
|
|
||||||
|
public void setNormalizationMin(double normalizationMin) { |
||||||
|
this.normalizationMin = normalizationMin; |
||||||
|
} |
||||||
|
|
||||||
|
public double getNormalizationMax() { |
||||||
|
return normalizationMax; |
||||||
|
} |
||||||
|
|
||||||
|
public void setNormalizationMax(double normalizationMax) { |
||||||
|
this.normalizationMax = normalizationMax; |
||||||
|
} |
||||||
|
|
||||||
|
public int getInputLayerNeuronCount() { |
||||||
|
return inputLayerNeuronCount; |
||||||
|
} |
||||||
|
|
||||||
|
public void setInputLayerNeuronCount(int inputLayerNeuronCount) { |
||||||
|
this.inputLayerNeuronCount = inputLayerNeuronCount; |
||||||
|
} |
||||||
|
|
||||||
|
public int getHiddenLayerNeuronCount() { |
||||||
|
return hiddenLayerNeuronCount; |
||||||
|
} |
||||||
|
|
||||||
|
public void setHiddenLayerNeuronCount(int hiddenLayerNeuronCount) { |
||||||
|
this.hiddenLayerNeuronCount = hiddenLayerNeuronCount; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOutputLayerNeuronCount() { |
||||||
|
return outputLayerNeuronCount; |
||||||
|
} |
||||||
|
|
||||||
|
public void setOutputLayerNeuronCount(int outputLayerNeuronCount) { |
||||||
|
this.outputLayerNeuronCount = outputLayerNeuronCount; |
||||||
|
} |
||||||
|
|
||||||
|
public ActivationFunction getActivationFunction() { |
||||||
|
return activationFunction; |
||||||
|
} |
||||||
|
|
||||||
|
public void setActivationFunction(ActivationFunction activationFunction) { |
||||||
|
this.activationFunction = activationFunction; |
||||||
|
} |
||||||
|
|
||||||
|
public double getPrecision() { |
||||||
|
return precision; |
||||||
|
} |
||||||
|
|
||||||
|
public void setPrecision(double precision) { |
||||||
|
this.precision = precision; |
||||||
|
} |
||||||
|
|
||||||
|
public int getMaxTimes() { |
||||||
|
return maxTimes; |
||||||
|
} |
||||||
|
|
||||||
|
public void setMaxTimes(int maxTimes) { |
||||||
|
this.maxTimes = maxTimes; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
package com.mh.algorithm.bpnn; |
||||||
|
|
||||||
|
import java.io.Serializable; |
||||||
|
|
||||||
|
public class Sigmoid implements ActivationFunction, Serializable { |
||||||
|
@Override |
||||||
|
public double computeValue(double val) { |
||||||
|
return 1 / (1 + Math.exp(-val)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public double computeDerivative(double val) { |
||||||
|
return computeValue(val) * (1 - computeValue(val)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
package com.mh.algorithm.constants; |
||||||
|
|
||||||
|
/** |
||||||
|
* 排序枚举类 |
||||||
|
*/ |
||||||
|
public enum OrderEnum { |
||||||
|
|
||||||
|
ASC(1,"升序"), |
||||||
|
|
||||||
|
DESC(2,"降序"); |
||||||
|
|
||||||
|
OrderEnum(int flag, String name) { |
||||||
|
|
||||||
|
this.flag = flag; |
||||||
|
|
||||||
|
this.name = name; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private int flag; |
||||||
|
|
||||||
|
private String name; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,88 @@ |
|||||||
|
package com.mh.algorithm.knn; |
||||||
|
|
||||||
|
import com.mh.algorithm.constants.OrderEnum; |
||||||
|
import com.mh.algorithm.matrix.Matrix; |
||||||
|
import com.mh.algorithm.utils.MatrixUtil; |
||||||
|
|
||||||
|
import java.util.*; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* @program: top-algorithm-set |
||||||
|
* @description: KNN k-临近算法进行分类 |
||||||
|
* @author: Mr.Zhao |
||||||
|
* @create: 2020-10-13 22:03 |
||||||
|
**/ |
||||||
|
public class KNN { |
||||||
|
public static Matrix classify(Matrix input, Matrix dataSet, Matrix labels, int k) throws Exception { |
||||||
|
if (dataSet.getMatrixRowCount() != labels.getMatrixRowCount()) { |
||||||
|
throw new IllegalArgumentException("矩阵训练集与标签维度不一致"); |
||||||
|
} |
||||||
|
if (input.getMatrixColCount() != dataSet.getMatrixColCount()) { |
||||||
|
throw new IllegalArgumentException("待分类矩阵列数与训练集列数不一致"); |
||||||
|
} |
||||||
|
if (dataSet.getMatrixRowCount() < k) { |
||||||
|
throw new IllegalArgumentException("训练集样本数小于k"); |
||||||
|
} |
||||||
|
// 归一化
|
||||||
|
int trainCount = dataSet.getMatrixRowCount(); |
||||||
|
int testCount = input.getMatrixRowCount(); |
||||||
|
Matrix trainAndTest = dataSet.splice(2, input); |
||||||
|
Map<String, Object> normalize = MatrixUtil.normalize(trainAndTest, 0, 1); |
||||||
|
trainAndTest = (Matrix) normalize.get("res"); |
||||||
|
dataSet = trainAndTest.subMatrix(0, trainCount, 0, trainAndTest.getMatrixColCount()); |
||||||
|
input = trainAndTest.subMatrix(0, testCount, 0, trainAndTest.getMatrixColCount()); |
||||||
|
|
||||||
|
// 获取标签信息
|
||||||
|
List<Double> labelList = new ArrayList<>(); |
||||||
|
for (int i = 0; i < labels.getMatrixRowCount(); i++) { |
||||||
|
if (!labelList.contains(labels.getValOfIdx(i, 0))) { |
||||||
|
labelList.add(labels.getValOfIdx(i, 0)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Matrix result = new Matrix(new double[input.getMatrixRowCount()][1]); |
||||||
|
for (int i = 0; i < input.getMatrixRowCount(); i++) { |
||||||
|
// 计算向量间的欧式距离
|
||||||
|
// 将labels矩阵扩展
|
||||||
|
Matrix labelMatrixCopied = input.getRowOfIdx(i).extend(2, dataSet.getMatrixRowCount()); |
||||||
|
// 前面是计算欧氏距离,splice(1,labels)是将距离矩阵与labels矩阵合并
|
||||||
|
Matrix distanceMatrix = dataSet.subtract(labelMatrixCopied).square().sumRow().pow(0.5).splice(1, labels); |
||||||
|
// 将计算出的距离矩阵按照距离升序排序
|
||||||
|
distanceMatrix.sort(0, OrderEnum.ASC); |
||||||
|
// 遍历最近的k个变量
|
||||||
|
Map<Double, Integer> map = new HashMap<>(); |
||||||
|
for (int j = 0; j < k; j++) { |
||||||
|
// 遍历标签种类数
|
||||||
|
for (Double label : labelList) { |
||||||
|
if (distanceMatrix.getValOfIdx(j, 1) == label) { |
||||||
|
map.put(label, map.getOrDefault(label, 0) + 1); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
result.setValue(i, 0, getKeyOfMaxValue(map)); |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 取map中值最大的key |
||||||
|
* |
||||||
|
* @param map |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private static Double getKeyOfMaxValue(Map<Double, Integer> map) { |
||||||
|
if (map == null) |
||||||
|
return null; |
||||||
|
Double keyOfMaxValue = 0.0; |
||||||
|
Integer maxValue = 0; |
||||||
|
for (Double key : map.keySet()) { |
||||||
|
if (map.get(key) > maxValue) { |
||||||
|
keyOfMaxValue = key; |
||||||
|
maxValue = map.get(key); |
||||||
|
} |
||||||
|
} |
||||||
|
return keyOfMaxValue; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,646 @@ |
|||||||
|
package com.mh.algorithm.matrix; |
||||||
|
|
||||||
|
import com.mh.algorithm.constants.OrderEnum; |
||||||
|
|
||||||
|
import java.io.Serializable; |
||||||
|
|
||||||
|
public class Matrix implements Serializable { |
||||||
|
private double[][] matrix; |
||||||
|
//矩阵列数
|
||||||
|
private int matrixColCount; |
||||||
|
//矩阵行数
|
||||||
|
private int matrixRowCount; |
||||||
|
|
||||||
|
/** |
||||||
|
* 构造一个空矩阵 |
||||||
|
*/ |
||||||
|
public Matrix() { |
||||||
|
this.matrix = null; |
||||||
|
this.matrixColCount = 0; |
||||||
|
this.matrixRowCount = 0; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 构造一个matrix矩阵 |
||||||
|
* @param matrix |
||||||
|
*/ |
||||||
|
public Matrix(double[][] matrix) { |
||||||
|
this.matrix = matrix; |
||||||
|
this.matrixRowCount = matrix.length; |
||||||
|
this.matrixColCount = matrix[0].length; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 构造一个rowCount行colCount列值为0的矩阵 |
||||||
|
* @param rowCount |
||||||
|
* @param colCount |
||||||
|
*/ |
||||||
|
public Matrix(int rowCount,int colCount) { |
||||||
|
double[][] matrix = new double[rowCount][colCount]; |
||||||
|
for (int i = 0; i < rowCount; i++) { |
||||||
|
for (int j = 0; j < colCount; j++) { |
||||||
|
matrix[i][j] = 0; |
||||||
|
} |
||||||
|
} |
||||||
|
this.matrix = matrix; |
||||||
|
this.matrixRowCount = rowCount; |
||||||
|
this.matrixColCount = colCount; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 构造一个rowCount行colCount列值为val的矩阵 |
||||||
|
* @param val |
||||||
|
* @param rowCount |
||||||
|
* @param colCount |
||||||
|
*/ |
||||||
|
public Matrix(double val,int rowCount,int colCount) { |
||||||
|
double[][] matrix = new double[rowCount][colCount]; |
||||||
|
for (int i = 0; i < rowCount; i++) { |
||||||
|
for (int j = 0; j < colCount; j++) { |
||||||
|
matrix[i][j] = val; |
||||||
|
} |
||||||
|
} |
||||||
|
this.matrix = matrix; |
||||||
|
this.matrixRowCount = rowCount; |
||||||
|
this.matrixColCount = colCount; |
||||||
|
} |
||||||
|
|
||||||
|
public double[][] getMatrix() { |
||||||
|
return matrix; |
||||||
|
} |
||||||
|
|
||||||
|
public void setMatrix(double[][] matrix) { |
||||||
|
this.matrix = matrix; |
||||||
|
this.matrixRowCount = matrix.length; |
||||||
|
this.matrixColCount = matrix[0].length; |
||||||
|
} |
||||||
|
|
||||||
|
public int getMatrixColCount() { |
||||||
|
return matrixColCount; |
||||||
|
} |
||||||
|
|
||||||
|
public int getMatrixRowCount() { |
||||||
|
return matrixRowCount; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取矩阵指定位置的值 |
||||||
|
* |
||||||
|
* @param x |
||||||
|
* @param y |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public double getValOfIdx(int x, int y) throws IllegalArgumentException { |
||||||
|
if (matrix == null || matrixRowCount == 0 || matrixColCount == 0) { |
||||||
|
throw new IllegalArgumentException("矩阵为空"); |
||||||
|
} |
||||||
|
if (x > matrixRowCount - 1) { |
||||||
|
throw new IllegalArgumentException("索引x越界"); |
||||||
|
} |
||||||
|
if (y > matrixColCount - 1) { |
||||||
|
throw new IllegalArgumentException("索引y越界"); |
||||||
|
} |
||||||
|
return matrix[x][y]; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取矩阵指定行 |
||||||
|
* |
||||||
|
* @param x |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public Matrix getRowOfIdx(int x) throws IllegalArgumentException { |
||||||
|
if (matrix == null || matrixRowCount == 0 || matrixColCount == 0) { |
||||||
|
throw new IllegalArgumentException("矩阵为空"); |
||||||
|
} |
||||||
|
if (x > matrixRowCount - 1) { |
||||||
|
throw new IllegalArgumentException("索引x越界"); |
||||||
|
} |
||||||
|
double[][] result = new double[1][matrixColCount]; |
||||||
|
result[0] = matrix[x]; |
||||||
|
return new Matrix(result); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取矩阵指定列 |
||||||
|
* |
||||||
|
* @param y |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public Matrix getColOfIdx(int y) throws IllegalArgumentException { |
||||||
|
if (matrix == null || matrixRowCount == 0 || matrixColCount == 0) { |
||||||
|
throw new IllegalArgumentException("矩阵为空"); |
||||||
|
} |
||||||
|
if (y > matrixColCount - 1) { |
||||||
|
throw new IllegalArgumentException("索引y越界"); |
||||||
|
} |
||||||
|
double[][] result = new double[matrixRowCount][1]; |
||||||
|
for (int i = 0; i < matrixRowCount; i++) { |
||||||
|
result[i][0] = matrix[i][y]; |
||||||
|
} |
||||||
|
return new Matrix(result); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 设置矩阵中x,y位置元素的值 |
||||||
|
* @param x |
||||||
|
* @param y |
||||||
|
* @param val |
||||||
|
*/ |
||||||
|
public void setValue(int x, int y, double val) { |
||||||
|
if (x > this.matrixRowCount - 1) { |
||||||
|
throw new IllegalArgumentException("行索引越界"); |
||||||
|
} |
||||||
|
if (y > this.matrixColCount - 1) { |
||||||
|
throw new IllegalArgumentException("列索引越界"); |
||||||
|
} |
||||||
|
this.matrix[x][y] = val; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 矩阵乘矩阵 |
||||||
|
* |
||||||
|
* @param a |
||||||
|
* @return |
||||||
|
* @throws IllegalArgumentException |
||||||
|
*/ |
||||||
|
public Matrix multiple(Matrix a) throws IllegalArgumentException { |
||||||
|
if (matrix == null || matrixRowCount == 0 || matrixColCount == 0) { |
||||||
|
throw new IllegalArgumentException("矩阵为空"); |
||||||
|
} |
||||||
|
if (a.getMatrix() == null || a.getMatrixRowCount() == 0 || a.getMatrixColCount() == 0) { |
||||||
|
throw new IllegalArgumentException("参数矩阵为空"); |
||||||
|
} |
||||||
|
if (matrixColCount != a.getMatrixRowCount()) { |
||||||
|
throw new IllegalArgumentException("矩阵纬度不同,不可计算"); |
||||||
|
} |
||||||
|
double[][] result = new double[matrixRowCount][a.getMatrixColCount()]; |
||||||
|
for (int i = 0; i < matrixRowCount; i++) { |
||||||
|
for (int j = 0; j < a.getMatrixColCount(); j++) { |
||||||
|
for (int k = 0; k < matrixColCount; k++) { |
||||||
|
result[i][j] = result[i][j] + matrix[i][k] * a.getMatrix()[k][j]; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return new Matrix(result); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 矩阵乘一个数字 |
||||||
|
* |
||||||
|
* @param a |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public Matrix multiple(double a) throws IllegalArgumentException { |
||||||
|
if (matrix == null || matrixRowCount == 0 || matrixColCount == 0) { |
||||||
|
throw new IllegalArgumentException("矩阵为空"); |
||||||
|
} |
||||||
|
double[][] result = new double[matrixRowCount][matrixColCount]; |
||||||
|
for (int i = 0; i < matrixRowCount; i++) { |
||||||
|
for (int j = 0; j < matrixColCount; j++) { |
||||||
|
result[i][j] = matrix[i][j] * a; |
||||||
|
} |
||||||
|
} |
||||||
|
return new Matrix(result); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 矩阵点乘 |
||||||
|
* |
||||||
|
* @param a |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public Matrix pointMultiple(Matrix a) throws IllegalArgumentException { |
||||||
|
if (matrix == null || matrixRowCount == 0 || matrixColCount == 0) { |
||||||
|
throw new IllegalArgumentException("矩阵为空"); |
||||||
|
} |
||||||
|
if (a.getMatrix() == null || a.getMatrixRowCount() == 0 || a.getMatrixColCount() == 0) { |
||||||
|
throw new IllegalArgumentException("参数矩阵为空"); |
||||||
|
} |
||||||
|
if (matrixRowCount != a.getMatrixRowCount() && matrixColCount != a.getMatrixColCount()) { |
||||||
|
throw new IllegalArgumentException("矩阵纬度不同,不可计算"); |
||||||
|
} |
||||||
|
double[][] result = new double[matrixRowCount][matrixColCount]; |
||||||
|
for (int i = 0; i < matrixRowCount; i++) { |
||||||
|
for (int j = 0; j < matrixColCount; j++) { |
||||||
|
result[i][j] = matrix[i][j] * a.getMatrix()[i][j]; |
||||||
|
} |
||||||
|
} |
||||||
|
return new Matrix(result); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 矩阵除一个数字 |
||||||
|
* @param a |
||||||
|
* @return |
||||||
|
* @throws IllegalArgumentException |
||||||
|
*/ |
||||||
|
public Matrix divide(double a) throws IllegalArgumentException { |
||||||
|
if (matrix == null || matrixRowCount == 0 || matrixColCount == 0) { |
||||||
|
throw new IllegalArgumentException("矩阵为空"); |
||||||
|
} |
||||||
|
double[][] result = new double[matrixRowCount][matrixColCount]; |
||||||
|
for (int i = 0; i < matrixRowCount; i++) { |
||||||
|
for (int j = 0; j < matrixColCount; j++) { |
||||||
|
result[i][j] = matrix[i][j] / a; |
||||||
|
} |
||||||
|
} |
||||||
|
return new Matrix(result); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 矩阵加法 |
||||||
|
* |
||||||
|
* @param a |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public Matrix plus(Matrix a) throws IllegalArgumentException { |
||||||
|
if (matrix == null || matrixRowCount == 0 || matrixColCount == 0) { |
||||||
|
throw new IllegalArgumentException("矩阵为空"); |
||||||
|
} |
||||||
|
if (a.getMatrix() == null || a.getMatrixRowCount() == 0 || a.getMatrixColCount() == 0) { |
||||||
|
throw new IllegalArgumentException("参数矩阵为空"); |
||||||
|
} |
||||||
|
if (matrixRowCount != a.getMatrixRowCount() && matrixColCount != a.getMatrixColCount()) { |
||||||
|
throw new IllegalArgumentException("矩阵纬度不同,不可计算"); |
||||||
|
} |
||||||
|
double[][] result = new double[matrixRowCount][matrixColCount]; |
||||||
|
for (int i = 0; i < matrixRowCount; i++) { |
||||||
|
for (int j = 0; j < matrixColCount; j++) { |
||||||
|
result[i][j] = matrix[i][j] + a.getMatrix()[i][j]; |
||||||
|
} |
||||||
|
} |
||||||
|
return new Matrix(result); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 矩阵加一个数字 |
||||||
|
* @param a |
||||||
|
* @return |
||||||
|
* @throws IllegalArgumentException |
||||||
|
*/ |
||||||
|
public Matrix plus(double a) throws IllegalArgumentException { |
||||||
|
if (matrix == null || matrixRowCount == 0 || matrixColCount == 0) { |
||||||
|
throw new IllegalArgumentException("矩阵为空"); |
||||||
|
} |
||||||
|
double[][] result = new double[matrixRowCount][matrixColCount]; |
||||||
|
for (int i = 0; i < matrixRowCount; i++) { |
||||||
|
for (int j = 0; j < matrixColCount; j++) { |
||||||
|
result[i][j] = matrix[i][j] + a; |
||||||
|
} |
||||||
|
} |
||||||
|
return new Matrix(result); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 矩阵减法 |
||||||
|
* |
||||||
|
* @param a |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public Matrix subtract(Matrix a) throws IllegalArgumentException { |
||||||
|
if (matrix == null || matrixRowCount == 0 || matrixColCount == 0) { |
||||||
|
throw new IllegalArgumentException("矩阵为空"); |
||||||
|
} |
||||||
|
if (a.getMatrix() == null || a.getMatrixRowCount() == 0 || a.getMatrixColCount() == 0) { |
||||||
|
throw new IllegalArgumentException("参数矩阵为空"); |
||||||
|
} |
||||||
|
if (matrixRowCount != a.getMatrixRowCount() && matrixColCount != a.getMatrixColCount()) { |
||||||
|
throw new IllegalArgumentException("矩阵纬度不同,不可计算"); |
||||||
|
} |
||||||
|
double[][] result = new double[matrixRowCount][matrixColCount]; |
||||||
|
for (int i = 0; i < matrixRowCount; i++) { |
||||||
|
for (int j = 0; j < matrixColCount; j++) { |
||||||
|
result[i][j] = matrix[i][j] - a.getMatrix()[i][j]; |
||||||
|
} |
||||||
|
} |
||||||
|
return new Matrix(result); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 矩阵减一个数字 |
||||||
|
* @param a |
||||||
|
* @return |
||||||
|
* @throws IllegalArgumentException |
||||||
|
*/ |
||||||
|
public Matrix subtract(double a) throws IllegalArgumentException { |
||||||
|
if (matrix == null || matrixRowCount == 0 || matrixColCount == 0) { |
||||||
|
throw new IllegalArgumentException("矩阵为空"); |
||||||
|
} |
||||||
|
double[][] result = new double[matrixRowCount][matrixColCount]; |
||||||
|
for (int i = 0; i < matrixRowCount; i++) { |
||||||
|
for (int j = 0; j < matrixColCount; j++) { |
||||||
|
result[i][j] = matrix[i][j] - a; |
||||||
|
} |
||||||
|
} |
||||||
|
return new Matrix(result); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 矩阵行求和 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public Matrix sumRow() throws IllegalArgumentException { |
||||||
|
if (matrix == null || matrixRowCount == 0 || matrixColCount == 0) { |
||||||
|
throw new IllegalArgumentException("矩阵为空"); |
||||||
|
} |
||||||
|
double[][] result = new double[matrixRowCount][1]; |
||||||
|
for (int i = 0; i < matrixRowCount; i++) { |
||||||
|
for (int j = 0; j < matrixColCount; j++) { |
||||||
|
result[i][0] += matrix[i][j]; |
||||||
|
} |
||||||
|
} |
||||||
|
return new Matrix(result); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 矩阵列求和 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public Matrix sumCol() throws IllegalArgumentException { |
||||||
|
if (matrix == null || matrixRowCount == 0 || matrixColCount == 0) { |
||||||
|
throw new IllegalArgumentException("矩阵为空"); |
||||||
|
} |
||||||
|
double[][] result = new double[1][matrixColCount]; |
||||||
|
for (int i = 0; i < matrixRowCount; i++) { |
||||||
|
for (int j = 0; j < matrixColCount; j++) { |
||||||
|
result[0][j] += matrix[i][j]; |
||||||
|
} |
||||||
|
} |
||||||
|
return new Matrix(result); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 矩阵所有元素求和 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public double sumAll() throws IllegalArgumentException { |
||||||
|
if (matrix == null || matrixRowCount == 0 || matrixColCount == 0) { |
||||||
|
throw new IllegalArgumentException("矩阵为空"); |
||||||
|
} |
||||||
|
double result = 0; |
||||||
|
for (double[] doubles : matrix) { |
||||||
|
for (int j = 0; j < matrixColCount; j++) { |
||||||
|
result += doubles[j]; |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 矩阵所有元素求平方 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public Matrix square() throws IllegalArgumentException { |
||||||
|
if (matrix == null || matrixRowCount == 0 || matrixColCount == 0) { |
||||||
|
throw new IllegalArgumentException("矩阵为空"); |
||||||
|
} |
||||||
|
double[][] result = new double[matrixRowCount][matrixColCount]; |
||||||
|
for (int i = 0; i < matrixRowCount; i++) { |
||||||
|
for (int j = 0; j < matrixColCount; j++) { |
||||||
|
result[i][j] = matrix[i][j] * matrix[i][j]; |
||||||
|
} |
||||||
|
} |
||||||
|
return new Matrix(result); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 矩阵所有元素求N次方 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public Matrix pow(double n) throws IllegalArgumentException { |
||||||
|
if (matrix == null || matrixRowCount == 0 || matrixColCount == 0) { |
||||||
|
throw new IllegalArgumentException("矩阵为空"); |
||||||
|
} |
||||||
|
double[][] result = new double[matrixRowCount][matrixColCount]; |
||||||
|
for (int i = 0; i < matrixRowCount; i++) { |
||||||
|
for (int j = 0; j < matrixColCount; j++) { |
||||||
|
result[i][j] = Math.pow(matrix[i][j],n); |
||||||
|
} |
||||||
|
} |
||||||
|
return new Matrix(result); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 矩阵转置 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public Matrix transpose() throws IllegalArgumentException { |
||||||
|
if (matrix == null || matrixRowCount == 0 || matrixColCount == 0) { |
||||||
|
throw new IllegalArgumentException("矩阵为空"); |
||||||
|
} |
||||||
|
double[][] result = new double[matrixColCount][matrixRowCount]; |
||||||
|
for (int i = 0; i < matrixRowCount; i++) { |
||||||
|
for (int j = 0; j < matrixColCount; j++) { |
||||||
|
result[j][i] = matrix[i][j]; |
||||||
|
} |
||||||
|
} |
||||||
|
return new Matrix(result); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 截取矩阵 |
||||||
|
* @param startRowIndex 开始行索引 |
||||||
|
* @param rowCount 截取行数 |
||||||
|
* @param startColIndex 开始列索引 |
||||||
|
* @param colCount 截取列数 |
||||||
|
* @return |
||||||
|
* @throws IllegalArgumentException |
||||||
|
*/ |
||||||
|
public Matrix subMatrix(int startRowIndex,int rowCount,int startColIndex,int colCount) throws IllegalArgumentException { |
||||||
|
if (startRowIndex + rowCount > matrixRowCount) { |
||||||
|
throw new IllegalArgumentException("行索引越界"); |
||||||
|
} |
||||||
|
if (startColIndex + colCount> matrixColCount) { |
||||||
|
throw new IllegalArgumentException("列索引越界"); |
||||||
|
} |
||||||
|
double[][] result = new double[rowCount][colCount]; |
||||||
|
for (int i = startRowIndex; i < startRowIndex + rowCount; i++) { |
||||||
|
if (startColIndex + colCount - startColIndex >= 0) |
||||||
|
System.arraycopy(matrix[i], startColIndex, result[i - startRowIndex], 0, colCount); |
||||||
|
} |
||||||
|
return new Matrix(result); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 矩阵合并 |
||||||
|
* @param direction 合并方向,1为横向,2为竖向 |
||||||
|
* @param a |
||||||
|
* @return |
||||||
|
* @throws IllegalArgumentException |
||||||
|
*/ |
||||||
|
public Matrix splice(int direction, Matrix a) throws IllegalArgumentException { |
||||||
|
if (matrix == null || matrixRowCount == 0 || matrixColCount == 0) { |
||||||
|
throw new IllegalArgumentException("矩阵为空"); |
||||||
|
} |
||||||
|
if (a.getMatrix() == null || a.getMatrixRowCount() == 0 || a.getMatrixColCount() == 0) { |
||||||
|
throw new IllegalArgumentException("参数矩阵为空"); |
||||||
|
} |
||||||
|
if(direction == 1){ |
||||||
|
//横向拼接
|
||||||
|
if (matrixRowCount != a.getMatrixRowCount()) { |
||||||
|
throw new IllegalArgumentException("矩阵行数不一致,无法拼接"); |
||||||
|
} |
||||||
|
double[][] result = new double[matrixRowCount][matrixColCount + a.getMatrixColCount()]; |
||||||
|
for (int i = 0; i < matrixRowCount; i++) { |
||||||
|
System.arraycopy(matrix[i],0,result[i],0,matrixColCount); |
||||||
|
System.arraycopy(a.getMatrix()[i],0,result[i],matrixColCount,a.getMatrixColCount()); |
||||||
|
} |
||||||
|
return new Matrix(result); |
||||||
|
}else if(direction == 2){ |
||||||
|
//纵向拼接
|
||||||
|
if (matrixColCount != a.getMatrixColCount()) { |
||||||
|
throw new IllegalArgumentException("矩阵列数不一致,无法拼接"); |
||||||
|
} |
||||||
|
double[][] result = new double[matrixRowCount + a.getMatrixRowCount()][matrixColCount]; |
||||||
|
for (int i = 0; i < matrixRowCount; i++) { |
||||||
|
result[i] = matrix[i]; |
||||||
|
} |
||||||
|
for (int i = 0; i < a.getMatrixRowCount(); i++) { |
||||||
|
result[matrixRowCount + i] = a.getMatrix()[i]; |
||||||
|
} |
||||||
|
return new Matrix(result); |
||||||
|
}else{ |
||||||
|
throw new IllegalArgumentException("方向参数有误"); |
||||||
|
} |
||||||
|
} |
||||||
|
/** |
||||||
|
* 扩展矩阵 |
||||||
|
* @param direction 扩展方向,1为横向,2为竖向 |
||||||
|
* @param a |
||||||
|
* @return |
||||||
|
* @throws IllegalArgumentException |
||||||
|
*/ |
||||||
|
public Matrix extend(int direction , int a) throws IllegalArgumentException { |
||||||
|
if (matrix == null || matrixRowCount == 0 || matrixColCount == 0) { |
||||||
|
throw new IllegalArgumentException("矩阵为空"); |
||||||
|
} |
||||||
|
if(direction == 1){ |
||||||
|
//横向复制
|
||||||
|
double[][] result = new double[matrixRowCount][matrixColCount*a]; |
||||||
|
for (int i = 0; i < matrixRowCount; i++) { |
||||||
|
for (int j = 0; j < a; j++) { |
||||||
|
System.arraycopy(matrix[i],0,result[i],j*matrixColCount,matrixColCount); |
||||||
|
} |
||||||
|
} |
||||||
|
return new Matrix(result); |
||||||
|
}else if(direction == 2){ |
||||||
|
//纵向复制
|
||||||
|
double[][] result = new double[matrixRowCount*a][matrixColCount]; |
||||||
|
for (int i = 0; i < matrixRowCount*a; i++) { |
||||||
|
result[i] = matrix[i%matrixRowCount]; |
||||||
|
} |
||||||
|
return new Matrix(result); |
||||||
|
}else{ |
||||||
|
throw new IllegalArgumentException("方向参数有误"); |
||||||
|
} |
||||||
|
} |
||||||
|
/** |
||||||
|
* 获取每列的平均值 |
||||||
|
* @return |
||||||
|
* @throws IllegalArgumentException |
||||||
|
*/ |
||||||
|
public Matrix getColAvg() throws IllegalArgumentException { |
||||||
|
Matrix tmp = this.sumCol(); |
||||||
|
return tmp.divide(matrixRowCount); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 矩阵行排序 |
||||||
|
* @param index 根据第几列的数进行行排序 |
||||||
|
* @param order 排序顺序,升序或降序 |
||||||
|
* @return |
||||||
|
* @throws IllegalArgumentException |
||||||
|
*/ |
||||||
|
public void sort(int index, OrderEnum order) throws IllegalArgumentException{ |
||||||
|
if (matrix == null || matrixRowCount == 0 || matrixColCount == 0) { |
||||||
|
throw new IllegalArgumentException("矩阵为空"); |
||||||
|
} |
||||||
|
if(index >= matrixColCount){ |
||||||
|
throw new IllegalArgumentException("排序索引index越界"); |
||||||
|
} |
||||||
|
sort(index,order,0,this.matrixRowCount - 1); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 判断是否是方阵 |
||||||
|
* 行列数相等,并且不等于0 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public boolean isSquareMatrix(){ |
||||||
|
return matrixColCount == matrixRowCount && matrixColCount != 0; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String toString() { |
||||||
|
StringBuilder stringBuilder = new StringBuilder(); |
||||||
|
stringBuilder.append("\r\n"); |
||||||
|
for (int i = 0; i < matrixRowCount; i++) { |
||||||
|
stringBuilder.append("# "); |
||||||
|
for (int j = 0; j < matrixColCount; j++) { |
||||||
|
stringBuilder.append(matrix[i][j]).append("\t "); |
||||||
|
} |
||||||
|
stringBuilder.append("#\r\n"); |
||||||
|
} |
||||||
|
stringBuilder.append("\r\n"); |
||||||
|
return stringBuilder.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
private void sort(int index,OrderEnum order,int start,int end){ |
||||||
|
if(start >= end){ |
||||||
|
return; |
||||||
|
} |
||||||
|
int tmp = partition(index,order,start,end); |
||||||
|
sort(index,order, start, tmp - 1); |
||||||
|
sort(index,order, tmp + 1, end); |
||||||
|
} |
||||||
|
|
||||||
|
private int partition(int index,OrderEnum order,int start,int end){ |
||||||
|
int l = start + 1,r = end; |
||||||
|
double v = matrix[start][index]; |
||||||
|
switch (order){ |
||||||
|
case ASC: |
||||||
|
while(true){ |
||||||
|
while(matrix[r][index] >= v && r > start){ |
||||||
|
r--; |
||||||
|
} |
||||||
|
while(matrix[l][index] <= v && l < end){ |
||||||
|
l++; |
||||||
|
} |
||||||
|
if(l >= r){ |
||||||
|
break; |
||||||
|
} |
||||||
|
double[] tmp = matrix[r]; |
||||||
|
matrix[r] = matrix[l]; |
||||||
|
matrix[l] = tmp; |
||||||
|
} |
||||||
|
break; |
||||||
|
case DESC: |
||||||
|
while(true){ |
||||||
|
while(matrix[r][index] <= v && r > start){ |
||||||
|
r--; |
||||||
|
} |
||||||
|
while(matrix[l][index] >= v && l < end){ |
||||||
|
l++; |
||||||
|
} |
||||||
|
if(l >= r){ |
||||||
|
break; |
||||||
|
} |
||||||
|
double[] tmp = matrix[r]; |
||||||
|
matrix[r] = matrix[l]; |
||||||
|
matrix[l] = tmp; |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
double[] tmp = matrix[r]; |
||||||
|
matrix[r] = matrix[start]; |
||||||
|
matrix[start] = tmp; |
||||||
|
return r; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,53 @@ |
|||||||
|
package com.mh.algorithm.utils; |
||||||
|
|
||||||
|
import com.mh.algorithm.matrix.Matrix; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
|
||||||
|
public class CsvInfo { |
||||||
|
private String[] header; |
||||||
|
private int csvRowCount; |
||||||
|
private int csvColCount; |
||||||
|
private ArrayList<String[]> csvFileList; |
||||||
|
|
||||||
|
public String[] getHeader() { |
||||||
|
return header; |
||||||
|
} |
||||||
|
|
||||||
|
public void setHeader(String[] header) { |
||||||
|
this.header = header; |
||||||
|
} |
||||||
|
|
||||||
|
public int getCsvRowCount() { |
||||||
|
return csvRowCount; |
||||||
|
} |
||||||
|
|
||||||
|
public int getCsvColCount() { |
||||||
|
return csvColCount; |
||||||
|
} |
||||||
|
|
||||||
|
public ArrayList<String[]> getCsvFileList() { |
||||||
|
return csvFileList; |
||||||
|
} |
||||||
|
|
||||||
|
public void setCsvFileList(ArrayList<String[]> csvFileList) { |
||||||
|
this.csvFileList = csvFileList; |
||||||
|
this.csvColCount = csvFileList.get(0) != null?csvFileList.get(0).length:0; |
||||||
|
this.csvRowCount = csvFileList.size(); |
||||||
|
} |
||||||
|
|
||||||
|
public Matrix toMatrix() throws Exception { |
||||||
|
double[][] arr = new double[csvFileList.size()][csvFileList.get(0).length]; |
||||||
|
for (int i = 0; i < csvFileList.size(); i++) { |
||||||
|
for (int j = 0; j < csvFileList.get(0).length; j++) { |
||||||
|
try { |
||||||
|
arr[i][j] = Double.parseDouble(csvFileList.get(i)[j]); |
||||||
|
}catch (NumberFormatException e){ |
||||||
|
throw new Exception("Csv中含有非数字字符,无法转换成Matrix对象"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return new Matrix(arr); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,66 @@ |
|||||||
|
package com.mh.algorithm.utils; |
||||||
|
|
||||||
|
import com.csvreader.CsvReader; |
||||||
|
import com.csvreader.CsvWriter; |
||||||
|
import com.mh.algorithm.matrix.Matrix; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.nio.charset.StandardCharsets; |
||||||
|
import java.util.ArrayList; |
||||||
|
|
||||||
|
public class CsvUtil { |
||||||
|
/** |
||||||
|
* 获取CSV中的信息 |
||||||
|
* @param hasHeader 是否含有表头 |
||||||
|
* @param path CSV文件的路径 |
||||||
|
* @return |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
public static CsvInfo getCsvInfo(boolean hasHeader , String path) throws IOException { |
||||||
|
//创建csv对象,存储csv中的信息
|
||||||
|
CsvInfo csvInfo = new CsvInfo(); |
||||||
|
//获取CsvReader流
|
||||||
|
CsvReader csvReader = new CsvReader(path, ',', StandardCharsets.UTF_8); |
||||||
|
if(hasHeader){ |
||||||
|
csvReader.readHeaders(); |
||||||
|
} |
||||||
|
//获取Csv中的所有记录
|
||||||
|
ArrayList<String[]> csvFileList = new ArrayList<String[]>(); |
||||||
|
while (csvReader.readRecord()) { |
||||||
|
csvFileList.add(csvReader.getValues()); |
||||||
|
} |
||||||
|
//赋值
|
||||||
|
csvInfo.setHeader(csvReader.getHeaders()); |
||||||
|
csvInfo.setCsvFileList(csvFileList); |
||||||
|
//关闭流
|
||||||
|
csvReader.close(); |
||||||
|
return csvInfo; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 将矩阵写入到csv文件中 |
||||||
|
* @param header 表头 |
||||||
|
* @param data 以矩阵形式存放的数据 |
||||||
|
* @param path 写入的文件地址 |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
public static void createCsvFile(String[] header,Matrix data,String path) throws Exception { |
||||||
|
|
||||||
|
if (header!=null && header.length != data.getMatrixColCount()) { |
||||||
|
throw new Exception("表头列数与数据列数不符"); |
||||||
|
} |
||||||
|
CsvWriter csvWriter = new CsvWriter(path, ',', StandardCharsets.UTF_8); |
||||||
|
|
||||||
|
if (header != null) { |
||||||
|
csvWriter.writeRecord(header); |
||||||
|
} |
||||||
|
for (int i = 0; i < data.getMatrixRowCount(); i++) { |
||||||
|
String[] record = new String[data.getMatrixColCount()]; |
||||||
|
for (int j = 0; j < data.getMatrixColCount(); j++) { |
||||||
|
record[j] = data.getValOfIdx(i, j)+""; |
||||||
|
} |
||||||
|
csvWriter.writeRecord(record); |
||||||
|
} |
||||||
|
csvWriter.close(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
package com.mh.algorithm.utils; |
||||||
|
|
||||||
|
/** |
||||||
|
* @program: top-algorithm-set |
||||||
|
* @description: DoubleTool |
||||||
|
* @author: Mr.Zhao |
||||||
|
* @create: 2020-11-12 21:54 |
||||||
|
**/ |
||||||
|
public class DoubleUtil { |
||||||
|
|
||||||
|
private static final Double MAX_ERROR = 0.0001; |
||||||
|
|
||||||
|
public static boolean equals(Double a, Double b) { |
||||||
|
return Math.abs(a - b)< MAX_ERROR; |
||||||
|
} |
||||||
|
|
||||||
|
public static boolean equals(Double a, Double b,Double maxError) { |
||||||
|
return Math.abs(a - b)< maxError; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,285 @@ |
|||||||
|
package com.mh.algorithm.utils; |
||||||
|
|
||||||
|
import Jama.EigenvalueDecomposition; |
||||||
|
import com.mh.algorithm.matrix.Matrix; |
||||||
|
|
||||||
|
import java.util.*; |
||||||
|
|
||||||
|
public class MatrixUtil { |
||||||
|
/** |
||||||
|
* 创建一个单位矩阵 |
||||||
|
* @param matrixRowCount 单位矩阵的纬度 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static Matrix eye(int matrixRowCount){ |
||||||
|
double[][] result = new double[matrixRowCount][matrixRowCount]; |
||||||
|
for (int i = 0; i < matrixRowCount; i++) { |
||||||
|
for (int j = 0; j < matrixRowCount; j++) { |
||||||
|
if(i == j){ |
||||||
|
result[i][j] = 1; |
||||||
|
}else{ |
||||||
|
result[i][j] = 0; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return new Matrix(result); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 求矩阵的逆 |
||||||
|
* 原理:AE=EA^-1 |
||||||
|
* @param a |
||||||
|
* @return |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
public static Matrix inv(Matrix a) throws Exception { |
||||||
|
if (!invable(a)) { |
||||||
|
throw new Exception("矩阵不可逆"); |
||||||
|
} |
||||||
|
// [a|E]
|
||||||
|
Matrix b = a.splice(1, eye(a.getMatrixRowCount())); |
||||||
|
double[][] data = b.getMatrix(); |
||||||
|
int rowCount = b.getMatrixRowCount(); |
||||||
|
int colCount = b.getMatrixColCount(); |
||||||
|
//此处应用a的列数,为简化,直接用b的行数
|
||||||
|
for (int j = 0; j < rowCount; j++) { |
||||||
|
//若遇到0则交换两行
|
||||||
|
int notZeroRow = -2; |
||||||
|
if(data[j][j] == 0){ |
||||||
|
notZeroRow = -1; |
||||||
|
for (int l = j; l < rowCount; l++) { |
||||||
|
if (data[l][j] != 0) { |
||||||
|
notZeroRow = l; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (notZeroRow == -1) { |
||||||
|
throw new Exception("矩阵不可逆"); |
||||||
|
}else if(notZeroRow != -2){ |
||||||
|
//交换j与notZeroRow两行
|
||||||
|
double[] tmp = data[j]; |
||||||
|
data[j] = data[notZeroRow]; |
||||||
|
data[notZeroRow] = tmp; |
||||||
|
} |
||||||
|
//将第data[j][j]化为1
|
||||||
|
if (data[j][j] != 1) { |
||||||
|
double multiple = data[j][j]; |
||||||
|
for (int colIdx = j; colIdx < colCount; colIdx++) { |
||||||
|
data[j][colIdx] /= multiple; |
||||||
|
} |
||||||
|
} |
||||||
|
//行与行相减
|
||||||
|
for (int i = 0; i < rowCount; i++) { |
||||||
|
if (i != j) { |
||||||
|
double multiple = data[i][j] / data[j][j]; |
||||||
|
//遍历行中的列
|
||||||
|
for (int k = j; k < colCount; k++) { |
||||||
|
data[i][k] = data[i][k] - multiple * data[j][k]; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
Matrix result = new Matrix(data); |
||||||
|
return result.subMatrix(0, rowCount, rowCount, rowCount); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 求矩阵的伴随矩阵 |
||||||
|
* 原理:A*=|A|A^-1 |
||||||
|
* @param a |
||||||
|
* @return |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
public static Matrix adj(Matrix a) throws Exception { |
||||||
|
return inv(a).multiple(det(a)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 矩阵转成上三角矩阵 |
||||||
|
* @param a |
||||||
|
* @return |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
public static Matrix getTopTriangle(Matrix a) throws Exception { |
||||||
|
if (!a.isSquareMatrix()) { |
||||||
|
throw new Exception("不是方阵无法进行计算"); |
||||||
|
} |
||||||
|
int matrixHeight = a.getMatrixRowCount(); |
||||||
|
double[][] result = a.getMatrix(); |
||||||
|
//遍历列
|
||||||
|
for (int j = 0; j < matrixHeight; j++) { |
||||||
|
//遍历行
|
||||||
|
for (int i = j+1; i < matrixHeight; i++) { |
||||||
|
//若遇到0则交换两行
|
||||||
|
int notZeroRow = -2; |
||||||
|
if(result[j][j] == 0){ |
||||||
|
notZeroRow = -1; |
||||||
|
for (int l = i; l < matrixHeight; l++) { |
||||||
|
if (result[l][j] != 0) { |
||||||
|
notZeroRow = l; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (notZeroRow == -1) { |
||||||
|
throw new Exception("矩阵不可逆"); |
||||||
|
}else if(notZeroRow != -2){ |
||||||
|
//交换j与notZeroRow两行
|
||||||
|
double[] tmp = result[j]; |
||||||
|
result[j] = result[notZeroRow]; |
||||||
|
result[notZeroRow] = tmp; |
||||||
|
} |
||||||
|
|
||||||
|
double multiple = result[i][j]/result[j][j]; |
||||||
|
//遍历行中的列
|
||||||
|
for (int k = j; k < matrixHeight; k++) { |
||||||
|
result[i][k] = result[i][k] - multiple * result[j][k]; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return new Matrix(result); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 计算矩阵的行列式 |
||||||
|
* @param a |
||||||
|
* @return |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
public static double det(Matrix a) throws Exception { |
||||||
|
//将矩阵转成上三角矩阵
|
||||||
|
Matrix b = MatrixUtil.getTopTriangle(a); |
||||||
|
double result = 1; |
||||||
|
//计算矩阵行列式
|
||||||
|
for (int i = 0; i < b.getMatrixRowCount(); i++) { |
||||||
|
result *= b.getValOfIdx(i, i); |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
/** |
||||||
|
* 获取协方差矩阵 |
||||||
|
* @param a |
||||||
|
* @return |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
public static Matrix cov(Matrix a) throws Exception { |
||||||
|
if (a.getMatrix() == null) { |
||||||
|
throw new Exception("矩阵为空"); |
||||||
|
} |
||||||
|
Matrix avg = a.getColAvg().extend(2, a.getMatrixRowCount()); |
||||||
|
Matrix tmp = a.subtract(avg); |
||||||
|
return tmp.transpose().multiple(tmp).multiple(1/((double) a.getMatrixRowCount() -1)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 判断矩阵是否可逆 |
||||||
|
* 如果可转为上三角矩阵则可逆 |
||||||
|
* @param a |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static boolean invable(Matrix a) { |
||||||
|
try { |
||||||
|
getTopTriangle(a); |
||||||
|
return true; |
||||||
|
} catch (Exception e) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取矩阵的特征值矩阵,调用Jama中的getV方法 |
||||||
|
* @param a |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static Matrix getV(Matrix a) { |
||||||
|
EigenvalueDecomposition eig = new EigenvalueDecomposition(new Jama.Matrix(a.getMatrix())); |
||||||
|
return new Matrix(eig.getV().getArray()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 取特征值实部 |
||||||
|
* @param a |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public double[] getRealEigenvalues(Matrix a){ |
||||||
|
EigenvalueDecomposition eig = new EigenvalueDecomposition(new Jama.Matrix(a.getMatrix())); |
||||||
|
return eig.getRealEigenvalues(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 取特征值虚部 |
||||||
|
* @param a |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public double[] getImagEigenvalues(Matrix a){ |
||||||
|
EigenvalueDecomposition eig = new EigenvalueDecomposition(new Jama.Matrix(a.getMatrix())); |
||||||
|
return eig.getImagEigenvalues(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 取块对角特征值矩阵 |
||||||
|
* @param a |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static Matrix getD(Matrix a) { |
||||||
|
EigenvalueDecomposition eig = new EigenvalueDecomposition(new Jama.Matrix(a.getMatrix())); |
||||||
|
return new Matrix(eig.getD().getArray()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 数据归一化 |
||||||
|
* @param a 要归一化的数据 |
||||||
|
* @param normalizationMin 要归一化的区间下限 |
||||||
|
* @param normalizationMax 要归一化的区间上限 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static Map<String, Object> normalize(Matrix a, double normalizationMin, double normalizationMax) throws Exception { |
||||||
|
HashMap<String, Object> result = new HashMap<>(); |
||||||
|
double[][] maxArr = new double[1][a.getMatrixColCount()]; |
||||||
|
double[][] minArr = new double[1][a.getMatrixColCount()]; |
||||||
|
double[][] res = new double[a.getMatrixRowCount()][a.getMatrixColCount()]; |
||||||
|
for (int i = 0; i < a.getMatrixColCount(); i++) { |
||||||
|
List tmp = new ArrayList(); |
||||||
|
for (int j = 0; j < a.getMatrixRowCount(); j++) { |
||||||
|
tmp.add(a.getValOfIdx(j,i)); |
||||||
|
} |
||||||
|
double max = (double) Collections.max(tmp); |
||||||
|
double min = (double) Collections.min(tmp); |
||||||
|
//数据归一化(注:若max与min均为0则不需要归一化)
|
||||||
|
if (max != 0 || min != 0) { |
||||||
|
for (int j = 0; j < a.getMatrixRowCount(); j++) { |
||||||
|
res[j][i] = normalizationMin + (a.getValOfIdx(j,i) - min) / (max - min) * (normalizationMax - normalizationMin); |
||||||
|
} |
||||||
|
} |
||||||
|
maxArr[0][i] = max; |
||||||
|
minArr[0][i] = min; |
||||||
|
} |
||||||
|
result.put("max", new Matrix(maxArr)); |
||||||
|
result.put("min", new Matrix(minArr)); |
||||||
|
result.put("res", new Matrix(res)); |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 反归一化 |
||||||
|
* @param a 要反归一化的数据 |
||||||
|
* @param normalizationMin 要反归一化的区间下限 |
||||||
|
* @param normalizationMax 要反归一化的区间上限 |
||||||
|
* @param dataMax 数据最大值 |
||||||
|
* @param dataMin 数据最小值 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static Matrix inverseNormalize(Matrix a, double normalizationMax, double normalizationMin , Matrix dataMax,Matrix dataMin){ |
||||||
|
double[][] res = new double[a.getMatrixRowCount()][a.getMatrixColCount()]; |
||||||
|
for (int i = 0; i < a.getMatrixColCount(); i++) { |
||||||
|
//数据反归一化
|
||||||
|
if (dataMin.getValOfIdx(0,i) != 0 || dataMax.getValOfIdx(0,i) != 0) { |
||||||
|
for (int j = 0; j < a.getMatrixRowCount(); j++) { |
||||||
|
res[j][i] = dataMin.getValOfIdx(0,i) + (dataMax.getValOfIdx(0,i) - dataMin.getValOfIdx(0,i)) * (a.getValOfIdx(j,i) - normalizationMin) / (normalizationMax - normalizationMin); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return new Matrix(res); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,32 @@ |
|||||||
|
package com.mh.algorithm.utils; |
||||||
|
|
||||||
|
import java.io.*; |
||||||
|
|
||||||
|
public class SerializationUtil { |
||||||
|
/** |
||||||
|
* 对象序列化到本地 |
||||||
|
* @param object |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
public static void serialize(Object object, String path) throws IOException { |
||||||
|
File file = new File(path); |
||||||
|
System.out.println(file.getAbsolutePath()); |
||||||
|
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file)); |
||||||
|
out.writeObject(object); |
||||||
|
out.close(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 对象反序列化 |
||||||
|
* @return |
||||||
|
* @throws IOException |
||||||
|
* @throws ClassNotFoundException |
||||||
|
*/ |
||||||
|
public static Object deSerialization(String path) throws IOException, ClassNotFoundException { |
||||||
|
File file = new File(path); |
||||||
|
ObjectInputStream oin = new ObjectInputStream(new FileInputStream(file)); |
||||||
|
Object object = oin.readObject(); |
||||||
|
oin.close(); |
||||||
|
return object; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,71 @@ |
|||||||
|
package com.mh.algorithm.bpnn; |
||||||
|
|
||||||
|
import com.mh.algorithm.matrix.Matrix; |
||||||
|
import com.mh.algorithm.utils.CsvInfo; |
||||||
|
import com.mh.algorithm.utils.CsvUtil; |
||||||
|
import com.mh.algorithm.utils.SerializationUtil; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
import java.util.Date; |
||||||
|
|
||||||
|
public class bpnnTest { |
||||||
|
@Test |
||||||
|
public void test() throws Exception { |
||||||
|
// 创建训练集矩阵
|
||||||
|
CsvInfo csvInfo = CsvUtil.getCsvInfo(true, "D:\\ljf\\my_pro\\top-algorithm-set-dev\\src\\trainDataElec.csv"); |
||||||
|
Matrix trainSet = csvInfo.toMatrix(); |
||||||
|
// 创建BPNN工厂对象
|
||||||
|
BPNeuralNetworkFactory factory = new BPNeuralNetworkFactory(); |
||||||
|
// 创建BP参数对象
|
||||||
|
BPParameter bpParameter = new BPParameter(); |
||||||
|
bpParameter.setInputLayerNeuronCount(2); |
||||||
|
bpParameter.setHiddenLayerNeuronCount(2); |
||||||
|
bpParameter.setOutputLayerNeuronCount(2); |
||||||
|
bpParameter.setPrecision(0.01); |
||||||
|
bpParameter.setMaxTimes(100000); |
||||||
|
|
||||||
|
// 训练BP神经网络
|
||||||
|
System.out.println(new Date()); |
||||||
|
BPModel bpModel = factory.trainBP(bpParameter, trainSet); |
||||||
|
System.out.println(new Date()); |
||||||
|
|
||||||
|
// 将BPModel序列化到本地
|
||||||
|
SerializationUtil.serialize(bpModel, "elec"); |
||||||
|
|
||||||
|
CsvInfo csvInfo2 = CsvUtil.getCsvInfo(true, "D:\\ljf\\my_pro\\top-algorithm-set-dev\\src\\testDataElec.csv"); |
||||||
|
Matrix testSet = csvInfo2.toMatrix(); |
||||||
|
|
||||||
|
Matrix testData1 = testSet.subMatrix(0, testSet.getMatrixRowCount(), 0, testSet.getMatrixColCount() - 2); |
||||||
|
Matrix testLabel = testSet.subMatrix(0, testSet.getMatrixRowCount(), testSet.getMatrixColCount() - 2, 1); |
||||||
|
// 将BPModel反序列化
|
||||||
|
BPModel bpModel1 = (BPModel) SerializationUtil.deSerialization("elec"); |
||||||
|
Matrix result = factory.computeBP(bpModel1, testData1); |
||||||
|
|
||||||
|
int total = result.getMatrixRowCount(); |
||||||
|
int correct = 0; |
||||||
|
for (int i = 0; i < result.getMatrixRowCount(); i++) { |
||||||
|
if(Math.round(result.getValOfIdx(i,0)) == testLabel.getValOfIdx(i,0)){ |
||||||
|
correct++; |
||||||
|
} |
||||||
|
} |
||||||
|
double correctRate = Double.valueOf(correct) / Double.valueOf(total); |
||||||
|
System.out.println(correctRate); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 使用示例 |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
@Test |
||||||
|
public void bpnnUsing() throws Exception{ |
||||||
|
CsvInfo csvInfo = CsvUtil.getCsvInfo(false, "D:\\ljf\\my_pro\\top-algorithm-set-dev\\src\\dataElec.csv"); |
||||||
|
Matrix data = csvInfo.toMatrix(); |
||||||
|
// 将BPModel反序列化
|
||||||
|
BPModel bpModel1 = (BPModel) SerializationUtil.deSerialization("elec"); |
||||||
|
// 创建工厂
|
||||||
|
BPNeuralNetworkFactory factory = new BPNeuralNetworkFactory(); |
||||||
|
Matrix result = factory.computeBP(bpModel1, data); |
||||||
|
CsvUtil.createCsvFile(null,result,"D:\\ljf\\my_pro\\top-algorithm-set-dev\\src\\computeResult.csv"); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,46 @@ |
|||||||
|
package com.mh.algorithm.knn; |
||||||
|
|
||||||
|
import com.mh.algorithm.matrix.Matrix; |
||||||
|
import com.mh.algorithm.utils.CsvInfo; |
||||||
|
import com.mh.algorithm.utils.CsvUtil; |
||||||
|
import com.mh.algorithm.utils.DoubleUtil; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
/** |
||||||
|
* @program: top-algorithm-set |
||||||
|
* @description: |
||||||
|
* @author: Mr.Zhao |
||||||
|
* @create: 2020-10-26 22:04 |
||||||
|
**/ |
||||||
|
public class knnTest { |
||||||
|
@Test |
||||||
|
public void test() throws Exception { |
||||||
|
// 训练集
|
||||||
|
CsvInfo csvInfo = CsvUtil.getCsvInfo(false, "E:\\jarTest\\trainData.csv"); |
||||||
|
Matrix trainSet = csvInfo.toMatrix(); |
||||||
|
Matrix trainSetLabels = trainSet.getColOfIdx(trainSet.getMatrixColCount() - 1); |
||||||
|
Matrix trainSetData = trainSet.subMatrix(0, trainSet.getMatrixRowCount(), 0, trainSet.getMatrixColCount() - 1); |
||||||
|
|
||||||
|
CsvInfo csvInfo1 = CsvUtil.getCsvInfo(false, "E:\\jarTest\\testData.csv"); |
||||||
|
Matrix testSet = csvInfo1.toMatrix(); |
||||||
|
Matrix testSetData = trainSet.subMatrix(0, testSet.getMatrixRowCount(), 0, testSet.getMatrixColCount() - 1); |
||||||
|
Matrix testSetLabels = trainSet.getColOfIdx(testSet.getMatrixColCount() - 1); |
||||||
|
|
||||||
|
// 分类
|
||||||
|
long startTime = System.currentTimeMillis(); |
||||||
|
Matrix result = KNN.classify(testSetData, trainSetData, trainSetLabels, 5); |
||||||
|
long endTime = System.currentTimeMillis(); |
||||||
|
System.out.println("run time:" + (endTime - startTime)); |
||||||
|
// 正确率
|
||||||
|
Matrix error = result.subtract(testSetLabels); |
||||||
|
int total = error.getMatrixRowCount(); |
||||||
|
int correct = 0; |
||||||
|
for (int i = 0; i < error.getMatrixRowCount(); i++) { |
||||||
|
if (DoubleUtil.equals(error.getValOfIdx(i, 0), 0.0)) { |
||||||
|
correct++; |
||||||
|
} |
||||||
|
} |
||||||
|
double correctRate = Double.valueOf(correct) / Double.valueOf(total); |
||||||
|
System.out.println("correctRate:"+ correctRate); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue