Skip to content

Commit 0f10f2d

Browse files
committed
precision at 0.72 at first
1 parent f1d9d96 commit 0f10f2d

5 files changed

Lines changed: 205 additions & 178 deletions

File tree

src/edu/hitsz/c102c/cnn/CNN.java

Lines changed: 92 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
import edu.hitsz.c102c.util.Util.Operator;
2020

2121
public class CNN {
22-
private static final double ALPHA = 0.01;
23-
protected static final double LAMBDA = 0.005;
22+
private static final double ALPHA = 1;
23+
protected static final double LAMBDA = 0;
2424
// 网络的各层
2525
private List<Layer> layers;
2626
// 层数
@@ -99,7 +99,7 @@ public void train(Dataset trainset, int repeat) {
9999
for (int t = 0; t < repeat; t++) {
100100
int epochsNum = 1 + trainset.size() / batchSize;// 多抽取一次,即向上取整
101101
for (int i = 0; i < epochsNum; i++) {
102-
int[] randPerm = Util.randomPerm(trainset.size(), batchSize);
102+
int[] randPerm = Util.randomPerm(trainset.size(), batchSize);
103103
Layer.prepareForNewBatch();
104104
for (int index : randPerm) {
105105
train(trainset.getRecord(index));
@@ -140,14 +140,20 @@ private double test(Dataset trainset) {
140140
double[][] outmap = outputLayer.getMap(m);
141141
out[m] = outmap[0][0];
142142
}
143+
// if (record.getLable().intValue() ==
144+
// Util.getMaxIndex(out))
145+
// right++;
143146
if (isSame(out, target)) {
144147
right++;
145-
// if (right % 1000 == 0)
146-
// Log.i("out:" + Arrays.toString(out) + " \n target:"
147-
// + Arrays.toString(target));
148+
// if (right % 1000 == 0)
149+
// Log.i("out:" + Arrays.toString(out)
150+
// + " \n target:"
151+
// + Arrays.toString(target));
148152
}
149-
Log.i("out:" + Arrays.toString(out) + " \n target:"
150-
+ Arrays.toString(target));
153+
154+
if (count++ % 1000 == 0)
155+
Log.i("out:" + Arrays.toString(out) + " \n target:"
156+
+ Arrays.toString(target));
151157
}
152158
return 1.0 * right / trainset.size();
153159
}
@@ -261,28 +267,33 @@ private void updateBias(Layer layer, Layer lastLayer) {
261267
private void updateKernels(Layer layer, Layer lastLayer) {
262268
int mapNum = layer.getOutMapNum();
263269
int lastMapNum = lastLayer.getOutMapNum();
270+
// double[][][][] errors = layer.getErrors();
271+
// double[][][][] lastMaps =
272+
// lastLayer.getMaps();
264273
for (int j = 0; j < mapNum; j++) {
265274
for (int i = 0; i < lastMapNum; i++) {
266-
double[][] kernel = layer.getKernel(i, j);
267-
double[][] deltaKernel = null;
275+
// double[][] deltaKernel = Util
276+
// .convnValid(lastMaps, i, errors, j);
268277
// 对batch的每个记录delta求和
278+
double[][] deltaKernel = null;
269279
for (int r = 0; r < batchSize; r++) {
270280
double[][] error = layer.getError(r, j);
271281
if (deltaKernel == null)
272-
deltaKernel = Util.convnValid(
273-
Util.rot180(lastLayer.getMap(r, i)), error);
282+
deltaKernel = Util.convnValid(lastLayer.getMap(r, i),
283+
error);
274284
else {// 累积求和
275-
deltaKernel = Util.matrixOp(Util.convnValid(
276-
Util.rot180(lastLayer.getMap(r, i)), error),
285+
deltaKernel = Util.matrixOp(
286+
Util.convnValid(lastLayer.getMap(r, i), error),
277287
deltaKernel, null, null, Util.plus);
278288
}
279289
}
280290

281291
// 除以batchSize
282292
deltaKernel = Util.matrixOp(deltaKernel, divide_batchSize);
283293
// 更新卷积核
294+
double[][] kernel = layer.getKernel(i, j);
284295
deltaKernel = Util.matrixOp(kernel, deltaKernel,
285-
multiply_lambda, multiply_alpha, Util.minus);
296+
multiply_lambda, multiply_alpha, Util.plus);
286297
layer.setKernel(i, j, deltaKernel);
287298
}
288299
}
@@ -344,37 +355,18 @@ private void setConvErrors(final Layer layer, final Layer nextLayer) {
344355
// 卷积层的下一层为采样层,即两层的map个数相同,且一个map只与令一层的一个map连接,
345356
// 因此只需将下一层的残差kronecker扩展再用点积即可
346357
int mapNum = layer.getOutMapNum();
347-
int cpuNum = ConcurenceRunner.cpuNum;
348-
cpuNum = cpuNum < mapNum ? cpuNum : 1;// 比cpu的个数小一个时,只用一个线程
349-
final CountDownLatch gate = new CountDownLatch(cpuNum);
350-
int fregLength = (mapNum + cpuNum - 1) / cpuNum;
351-
for (int cpu = 0; cpu < cpuNum; cpu++) {
352-
int start = cpu * fregLength;
353-
int tmp = (cpu + 1) * fregLength;
354-
int end = tmp <= mapNum ? tmp : mapNum;
355-
Task task = new Task(start, end) {
356-
357-
@Override
358-
public void process(int start, int end) {
359-
for (int m = start; m < end; m++) {
360-
Size scale = nextLayer.getScaleSize();
361-
double[][] nextError = nextLayer.getError(m);
362-
double[][] map = layer.getMap(m);
363-
// 矩阵相乘,但对第二个矩阵的每个元素value进行1-value操作
364-
double[][] outMatrix = Util.matrixOp(map,
365-
Util.cloneMatrix(map), null, Util.one_value,
366-
Util.multiply);
367-
outMatrix = Util.matrixOp(outMatrix,
368-
Util.kronecker(nextError, scale), null, null,
369-
Util.multiply);
370-
layer.setError(m, outMatrix);
371-
}
372-
gate.countDown();
373-
}
374-
};
375-
runner.run(task);
358+
for (int m = 0; m < mapNum; m++) {
359+
Size scale = nextLayer.getScaleSize();
360+
double[][] nextError = nextLayer.getError(m);
361+
double[][] map = layer.getMap(m);
362+
// 矩阵相乘,但对第二个矩阵的每个元素value进行1-value操作
363+
double[][] outMatrix = Util.matrixOp(map, Util.cloneMatrix(map),
364+
null, Util.one_value, Util.multiply);
365+
outMatrix = Util
366+
.matrixOp(outMatrix, Util.kronecker(nextError, scale),
367+
null, null, Util.multiply);
368+
layer.setError(m, outMatrix);
376369
}
377-
await(gate);
378370

379371
}
380372

@@ -384,15 +376,32 @@ public void process(int start, int end) {
384376
* @param record
385377
*/
386378
private void setOutLayerErrors(Record record) {
379+
387380
Layer outputLayer = layers.get(layerNum - 1);
388381
int mapNum = outputLayer.getOutMapNum();
389-
double[] target = record.getDoubleEncodeTarget(mapNum);
390-
for (int m = 0; m < mapNum; m++) {
391-
double[][] outmap = outputLayer.getMap(m);
392-
double output = outmap[0][0];
393-
double errors = output * (1 - output) * (target[m] - output);
394-
outputLayer.setError(m, 0, 0, errors);
395-
}
382+
double[] target =
383+
record.getDoubleEncodeTarget(mapNum);
384+
for (int m = 0; m < mapNum; m++) {
385+
double[][] outmap = outputLayer.getMap(m);
386+
double output = outmap[0][0];
387+
double errors = output * (1 - output) *
388+
(target[m] - output);
389+
outputLayer.setError(m, 0, 0, errors);
390+
}
391+
392+
// double[] errors = new double[mapNum];
393+
// double[] outmaps = new double[mapNum];
394+
// for (int m = 0; m < mapNum; m++) {
395+
// double[][] outmap = outputLayer.getMap(m);
396+
// outmaps[m] = outmap[0][0];
397+
//
398+
// }
399+
//
400+
// errors[record.getLable().intValue()] = 1;
401+
// for (int m = 0; m < mapNum; m++) {
402+
// outputLayer.setError(m, 0, 0, outmaps[m] * (1 - outmaps[m])
403+
// * (errors[m] - outmaps[m]));
404+
// }
396405
}
397406

398407
/**
@@ -433,32 +442,12 @@ private void setInLayerOutput(Record record) {
433442
final double[] attr = record.getAttrs();
434443
if (attr.length != mapSize.x * mapSize.y)
435444
throw new RuntimeException("数据记录的大小与定义的map大小不一致!");
436-
int cpuNum = ConcurenceRunner.cpuNum;
437-
cpuNum = cpuNum < mapSize.y ? cpuNum : 1;// 比cpu的个数小一个时,只用一个线程
438-
final CountDownLatch gate = new CountDownLatch(cpuNum);
439-
int fregLength = (mapSize.y + cpuNum - 1) / cpuNum;
440-
for (int cpu = 0; cpu < cpuNum; cpu++) {
441-
int start = cpu * fregLength;
442-
int tmp = (cpu + 1) * fregLength;
443-
int end = tmp <= mapSize.y ? tmp : mapSize.y;
444-
Task task = new Task(start, end) {
445-
446-
@Override
447-
public void process(int start, int end) {
448-
449-
for (int i = 0; i < mapSize.x; i++) {
450-
for (int j = start; j < end; j++) {
451-
// 将记录属性的一维向量弄成二维矩阵
452-
double value = attr[mapSize.x * i + j];
453-
inputLayer.setMapValue(0, i, j, value);
454-
}
455-
}
456-
gate.countDown();
457-
}
458-
};
459-
runner.run(task);
445+
for (int i = 0; i < mapSize.x; i++) {
446+
for (int j = 0; j < mapSize.y; j++) {
447+
// 将记录属性的一维向量弄成二维矩阵
448+
inputLayer.setMapValue(0, i, j, attr[mapSize.x * i + j]);
449+
}
460450
}
461-
await(gate);
462451
}
463452

464453
/*
@@ -467,49 +456,30 @@ public void process(int start, int end) {
467456
private void setConvOutput(final Layer layer, final Layer lastLayer) {
468457
int mapNum = layer.getOutMapNum();
469458
final int lastMapNum = lastLayer.getOutMapNum();
470-
int cpuNum = ConcurenceRunner.cpuNum;
471-
cpuNum = cpuNum < mapNum ? cpuNum : 1;// 比cpu的个数小一个时,只用一个线程
472-
final CountDownLatch gate = new CountDownLatch(cpuNum);
473-
int fregLength = (mapNum + cpuNum - 1) / cpuNum;
474-
for (int cpu = 0; cpu < cpuNum; cpu++) {
475-
int start = cpu * fregLength;
476-
int tmp = (cpu + 1) * fregLength;
477-
int end = tmp <= mapNum ? tmp : mapNum;
478-
Task task = new Task(start, end) {
459+
for (int j = 0; j < mapNum; j++) {
460+
double[][] sum = null;// 对每一个输入map的卷积进行求和
461+
for (int i = 0; i < lastMapNum; i++) {
462+
double[][] lastMap = lastLayer.getMap(i);
463+
double[][] kernel = layer.getKernel(i, j);
464+
if (sum == null)
465+
sum = Util.convnValid(lastMap, kernel);
466+
else
467+
sum = Util.matrixOp(Util.convnValid(lastMap, kernel), sum,
468+
null, null, Util.plus);
469+
}
470+
final double bias = layer.getBias(j);
471+
sum = Util.matrixOp(sum, new Operator() {
479472

480473
@Override
481-
public void process(int start, int end) {
482-
for (int j = start; j < end; j++) {
483-
double[][] sum = null;// 对每一个输入map的卷积进行求和
484-
for (int i = 0; i < lastMapNum; i++) {
485-
double[][] lastMap = lastLayer.getMap(i);
486-
double[][] kernel = layer.getKernel(i, j);
487-
if (sum == null)
488-
sum = Util.convnValid(lastMap, kernel);
489-
else
490-
sum = Util.matrixOp(
491-
Util.convnValid(lastMap, kernel), sum,
492-
null, null, Util.plus);
493-
}
494-
final double bias = layer.getBias(j);
495-
sum = Util.matrixOp(sum, new Operator() {
496-
497-
@Override
498-
public double process(double value) {
499-
return Util.sigmod(value + bias);
500-
}
501-
502-
});
503-
if (sum[0][0] > 1)
504-
Log.i(sum[0][0] + "");
505-
layer.setMapValue(j, sum);
506-
}
507-
gate.countDown();
474+
public double process(double value) {
475+
return Util.sigmod(value + bias);
508476
}
509-
};
510-
runner.run(task);
477+
478+
});
479+
if (sum[0][0] > 1)
480+
Log.i(sum[0][0] + "");
481+
layer.setMapValue(j, sum);
511482
}
512-
await(gate);
513483

514484
}
515485

@@ -521,32 +491,13 @@ public double process(double value) {
521491
*/
522492
private void setSampOutput(final Layer layer, final Layer lastLayer) {
523493
int lastMapNum = lastLayer.getOutMapNum();
524-
int cpuNum = ConcurenceRunner.cpuNum;
525-
cpuNum = cpuNum < lastMapNum ? cpuNum : 1;// 比cpu的个数小一个时,只用一个线程
526-
final CountDownLatch gate = new CountDownLatch(cpuNum);
527-
int fregLength = (lastMapNum + cpuNum - 1) / cpuNum;
528-
for (int cpu = 0; cpu < cpuNum; cpu++) {
529-
int start = cpu * fregLength;
530-
int tmp = (cpu + 1) * fregLength;
531-
int end = tmp <= lastMapNum ? tmp : lastMapNum;
532-
Task task = new Task(start, end) {
533-
534-
@Override
535-
public void process(int start, int end) {
536-
for (int i = start; i < end; i++) {
537-
double[][] lastMap = lastLayer.getMap(i);
538-
Size scaleSize = layer.getScaleSize();
539-
// 按scaleSize区域进行均值处理
540-
double[][] sampMatrix = Util.scaleMatrix(lastMap,
541-
scaleSize);
542-
layer.setMapValue(i, sampMatrix);
543-
}
544-
gate.countDown();
545-
}
546-
};
547-
runner.run(task);
494+
for (int i = 0; i < lastMapNum; i++) {
495+
double[][] lastMap = lastLayer.getMap(i);
496+
Size scaleSize = layer.getScaleSize();
497+
// 按scaleSize区域进行均值处理
498+
double[][] sampMatrix = Util.scaleMatrix(lastMap, scaleSize);
499+
layer.setMapValue(i, sampMatrix);
548500
}
549-
await(gate);
550501
}
551502

552503
/**

src/edu/hitsz/c102c/cnn/Layer.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ public static Layer buildOutputLayer(int classNum) {
9898
int outMapNum = 1;
9999
while ((1 << outMapNum) < classNum)
100100
outMapNum += 1;
101-
layer.outMapNum = outMapNum;
102-
Log.i("outMapNum" + outMapNum);
101+
layer.outMapNum = outMapNum;
102+
Log.i("outMapNum:" + layer.outMapNum);
103103
return layer;
104104
}
105105

@@ -223,7 +223,6 @@ public Size subtract(Size size, int append) {
223223
return new Size(x, y);
224224
}
225225
}
226-
227226

228227
/**
229228
* 随机初始化卷积核
@@ -341,6 +340,8 @@ public void setError(int mapNo, int mapX, int mapY, double value) {
341340
* @param matrix
342341
*/
343342
public void setError(int mapNo, double[][] matrix) {
343+
// Log.i(type.toString());
344+
// Util.printMatrix(matrix);
344345
errors[recordInBatch][mapNo] = matrix;
345346
}
346347

@@ -380,8 +381,6 @@ public void initErros(int batchSize) {
380381
* @param kernel
381382
*/
382383
public void setKernel(int lastMapNo, int mapNo, double[][] kernel) {
383-
// if(type == LayerType.output)
384-
// Util.printMatrix(kernel);
385384
this.kernel[lastMapNo][mapNo] = kernel;
386385
}
387386

@@ -446,4 +445,13 @@ public static int getClassNum() {
446445
return classNum;
447446
}
448447

448+
/**
449+
* 获取所有的卷积核
450+
*
451+
* @return
452+
*/
453+
public double[][][][] getKernel() {
454+
return kernel;
455+
}
456+
449457
}

0 commit comments

Comments
 (0)