I'm writting a FCN example,the program can run ,but accuracy is very poor, always about 0.33
Here is the code i write, to find the problem, I change the code so the program just train one image for 10000 times.
This code mainly refer to caffee model and FCN of mxnet python version
#include <iostream>
#include <fstream>
#include <map>
#include <string>
#include <stdint.h>
#include <vector>
#include "MxNetCpp.h"
#include "readmnist.h"
#include "opencv2/opencv.hpp"
using namespace std;
using namespace mxnet::cpp;
using namespace cv;
class Lenet {
public:
Lenet()
: ctx_cpu(Context(DeviceType::kCPU, 0)),
ctx_dev(Context(DeviceType::kGPU, 0)) {}
void Run() {
/*
* LeCun, Yann, Leon Bottou, Yoshua Bengio, and Patrick Haffner.
* "Gradient-based learning applied to document recognition."
* Proceedings of the IEEE (1998)
* */
/*define the symbolic net*/
Symbol data = Symbol::Variable("data");
Symbol data_label = Symbol::Variable("data_label");
Symbol conv1_1_w = Symbol::Variable("conv1_1_w");
Symbol conv1_1_b = Symbol::Variable("conv1_1_b");
Symbol conv1_2_w = Symbol::Variable("conv1_2_w");
Symbol conv1_2_b = Symbol::Variable("conv1_2_b");
Symbol conv2_1_w = Symbol::Variable("conv2_1_w");
Symbol conv2_1_b = Symbol::Variable("conv2_1_b");
Symbol conv2_2_w = Symbol::Variable("conv2_2_w");
Symbol conv2_2_b = Symbol::Variable("conv2_2_b");
Symbol conv3_1_w = Symbol::Variable("conv3_1_w");
Symbol conv3_1_b = Symbol::Variable("conv3_1_b");
Symbol conv3_2_w = Symbol::Variable("conv3_2_w");
Symbol conv3_2_b = Symbol::Variable("conv3_2_b");
Symbol conv4_1_w = Symbol::Variable("conv4_1_w");
Symbol conv4_1_b = Symbol::Variable("conv4_1_b");
Symbol conv4_2_w = Symbol::Variable("conv4_2_w");
Symbol conv4_2_b = Symbol::Variable("conv4_2_b");
Symbol conv4_3_w = Symbol::Variable("conv4_3_w");
Symbol conv4_3_b = Symbol::Variable("conv4_3_b");
Symbol conv5_1_w = Symbol::Variable("conv5_1_w");
Symbol conv5_1_b = Symbol::Variable("conv5_1_b");
Symbol conv5_2_w = Symbol::Variable("conv5_2_w");
Symbol conv5_2_b = Symbol::Variable("conv5_2_b");
Symbol conv5_3_w = Symbol::Variable("conv5_3_w");
Symbol conv5_3_b = Symbol::Variable("conv5_3_b");
Symbol fc6_w = Symbol::Variable("fc6_w");
Symbol fc6_b = Symbol::Variable("fc6_b");
Symbol fc7_b = Symbol::Variable("fc7_b");
Symbol fc7_w = Symbol::Variable("fc7_w");
Symbol score_fr_b = Symbol::Variable("score_fr_b");
Symbol score_fr_w = Symbol::Variable("score_fr_w");
Symbol bigscore_b = Symbol::Variable("bigscore_b");
Symbol bigscore_w = Symbol::Variable("bigscore_w");
Symbol conv1_1 =
Convolution("conv1_1", data, conv1_1_w, conv1_1_b, Shape(3, 3), 64, Shape(1, 1), Shape(1, 1), Shape(100, 100));
Symbol tanh1_1 = Activation("tanh1_1", conv1_1, ActivationActType::sigmoid);
Symbol conv1_2 =
Convolution("conv1_2", tanh1_1, conv1_2_w, conv1_2_b, Shape(3, 3), 64, Shape(1, 1), Shape(1, 1), Shape(1, 1));
Symbol tanh1_2 = Activation("tanh1_2", conv1_2, ActivationActType::sigmoid);
Symbol pool1 = Pooling("pool1", tanh1_2, Shape(2, 2),
PoolingPoolType::max, Shape(2, 2));
Symbol conv2_1 =
Convolution("conv2_1", pool1, conv2_1_w, conv2_1_b, Shape(3, 3), 128, Shape(1, 1), Shape(1, 1), Shape(1, 1));
Symbol tanh2_1 = Activation("tanh2_1", conv2_1, ActivationActType::sigmoid);
Symbol conv2_2 =
Convolution("conv2_2", tanh2_1, conv2_2_w, conv2_2_b, Shape(3, 3), 128, Shape(1, 1), Shape(1, 1), Shape(1, 1));
Symbol tanh2_2 = Activation("tanh2_2", conv2_2, ActivationActType::sigmoid);
Symbol pool2 = Pooling("pool2", tanh2_2, Shape(2, 2),
PoolingPoolType::max, Shape(2, 2));
Symbol conv3_1 =
Convolution("conv3_1", pool2, conv3_1_w, conv3_1_b, Shape(3, 3), 256, Shape(1, 1), Shape(1, 1), Shape(1, 1));
Symbol tanh3_1 = Activation("tanh3_1", conv3_1, ActivationActType::sigmoid);
Symbol conv3_2 =
Convolution("conv3_2", tanh3_1, conv3_2_w, conv3_2_b, Shape(3, 3), 256, Shape(1, 1), Shape(1, 1), Shape(1, 1));
Symbol tanh3_2 = Activation("tanh3_2", conv3_2, ActivationActType::sigmoid);
Symbol pool3 = Pooling("pool3", tanh3_2, Shape(2, 2),
PoolingPoolType::max, Shape(2, 2));
Symbol conv4_1 =
Convolution("conv4_1", pool3, conv4_1_w, conv4_1_b, Shape(3, 3), 512, Shape(1, 1), Shape(1, 1), Shape(1, 1));
Symbol tanh4_1 = Activation("tanh4_1", conv4_1, ActivationActType::sigmoid);
Symbol conv4_2 =
Convolution("conv4_2", tanh4_1, conv4_2_w, conv4_2_b, Shape(3, 3), 512, Shape(1, 1), Shape(1, 1), Shape(1, 1));
Symbol tanh4_2 = Activation("tanh4_2", conv4_2, ActivationActType::sigmoid);
Symbol conv4_3 =
Convolution("conv4_3", tanh4_2, conv4_3_w, conv4_3_b, Shape(3, 3), 512, Shape(1, 1), Shape(1, 1), Shape(1, 1));
Symbol tanh4_3 = Activation("tanh4_3", conv4_3, ActivationActType::sigmoid);
Symbol pool4 = Pooling("pool4", tanh4_3, Shape(2, 2),
PoolingPoolType::max, Shape(2, 2));
Symbol conv5_1 =
Convolution("conv5_1", pool4, conv5_1_w, conv5_1_b, Shape(3, 3), 512, Shape(1, 1), Shape(1, 1), Shape(1, 1));
Symbol tanh5_1 = Activation("tanh5_1", conv5_1, ActivationActType::sigmoid);
Symbol conv5_2 =
Convolution("conv5_2", tanh5_1, conv5_2_w, conv5_2_b, Shape(3, 3), 512, Shape(1, 1), Shape(1, 1), Shape(1, 1));
Symbol tanh5_2 = Activation("tanh5_2", conv5_2, ActivationActType::sigmoid);
Symbol conv5_3 =
Convolution("conv5_3", tanh5_2, conv5_3_w, conv5_3_b, Shape(3, 3), 512, Shape(1, 1), Shape(1, 1), Shape(1, 1));
Symbol tanh5_3 = Activation("tanh5_3", conv5_3, ActivationActType::sigmoid);
Symbol pool5 = Pooling("pool5", tanh5_3, Shape(2, 2),
PoolingPoolType::max, Shape(2, 2));
Symbol fc6 =
Convolution("fc6", pool5, fc6_w, fc6_b, Shape(7, 7), 4096);
Symbol tanh6 = Activation("tanh6", fc6, ActivationActType::sigmoid);
Symbol drop6 = Dropout("drop6", tanh6, 0.5);
Symbol fc7 =
Convolution("fc7", drop6, fc7_w, fc7_b, Shape(1, 1), 4096);
Symbol tanh7 = Activation("tanh7", fc7, ActivationActType::sigmoid);
Symbol drop7 = Dropout("drop7", tanh7, 0.5);
Symbol score_fr =
Convolution("score_fr", drop7, score_fr_w, score_fr_b, Shape(1, 1), 3);
Symbol bigscore = Deconvolution("bigscore", score_fr, bigscore_w, bigscore_b, Shape(64, 64), 3, Shape(32, 32));
Symbol upscore = Crop("upscore", 2,bigscore, data);
/*Crop函数暂将op.h文件中的Crop定义改为了
inline Symbol Crop(const std::string& symbol_name,
int num_args,
Symbol data,
Symbol crop_like,
Shape offset = Shape(0, 0),
Shape h_w = Shape(0, 0),
bool center_crop = false) {
return Operator("Crop")
.SetParam("num_args", num_args)
.SetParam("offset", offset)
.SetParam("h_w", h_w)
.SetParam("center_crop", center_crop)
.SetInput("arg0", data)
.SetInput("arg1", crop_like)
.CreateSymbol(symbol_name);
} */
Symbol lenet = SoftmaxOutput("lenet",upscore, data_label,1,255,true,true);
for (auto s : lenet.ListArguments()) {
LG << s;
}
/*setup basic configs*/
int batch_size = 1;
int max_epoch = 100;
float learning_rate = 1e-10;
float weight_decay = 0.0005;
vector<float> data_vec, label_vec;
size_t data_count = getData(data_vec, label_vec);
const float *dptr = data_vec.data();
const float *lptr = label_vec.data();
NDArray data_array = NDArray(Shape(data_count, 1,W,H), ctx_cpu,
false); // store in main memory, and copy to
// device memory while training
NDArray label_array =
NDArray(Shape(data_count,1*W*H), ctx_cpu,
false); // it's also ok if just store them all in device memory
data_array.SyncCopyFromCPU(dptr, data_count * W * H);
label_array.SyncCopyFromCPU(lptr, data_count * W * H);
data_array.WaitToRead();
label_array.WaitToRead();
size_t train_num = 1;
train_data = data_array.Slice(0, train_num);
train_label = label_array.Slice(0, train_num);
val_data = data_array.Slice(0, 1);
val_label = label_array.Slice(0, 1);
LG << "here read fin";
args_map["data"] =
NDArray(Shape(batch_size, 1, W, H), ctx_dev, false);
lenet.InferArgsMap(ctx_dev, &args_map, args_map);
NDArray::WaitAll();
LG << "here slice fin";
Optimizer opt("ccsgd", learning_rate, weight_decay);
opt.SetParam("momentum", 0.99)
.SetParam("rescale_grad", 1.0)
.SetParam("clip_gradient", 10);
for (int m = 0; m < 100; m++)
{
for (int ITER = 0; ITER < max_epoch; ++ITER) {
args_map["data"] =
train_data.Slice(0, 1)
.Copy(ctx_dev);
args_map["data_label"] = train_label.Slice(0, 1)
.Copy(ctx_dev);
NDArray::WaitAll();
Executor *exe = lenet.SimpleBind(ctx_dev, args_map);
exe->Forward(true);
const auto &out = exe->outputs;
NDArray out_cpu = out[0].Copy(ctx_cpu);
vector<mx_uint> shape_out = out_cpu.GetShape();
exe->Backward();
exe->UpdateAll(&opt, learning_rate, weight_decay);
delete exe;
}
LG <<"Iter"<< m <<", accuracy: " << ValAccuracy(batch_size, lenet);
}
}
private:
Context ctx_cpu;
Context ctx_dev;
map<string, NDArray> args_map;
NDArray train_data;
NDArray train_label;
NDArray val_data;
NDArray val_label;
int W = 200;
int H = 200;
size_t getData(vector<float> &vec, vector<float> &vecl)
{
int number_of_images = 0;
Mat I = cv::imread("1.jpg", 0);//读取灰度图
uchar* p = I.data;
for (unsigned int j = 0; j < 40000; ++j)
{
vec.push_back(*p);
p++;
}
//分割之后图像背景像素值为0,其他为38,飞机为220,分别用0,1,2来表示
I = cv::imread("1.png", 0);
p = I.data;
for (unsigned int j = 0; j <40000; ++j)
{
if (*p == 220)
vecl.push_back(2);
else if (*p == 38)
vecl.push_back(1);
else
vecl.push_back(0);
p++;
}
number_of_images++;
return number_of_images;
}
float ValAccuracy(int batch_size, Symbol lenet) {
size_t val_num = val_data.GetShape()[0];
size_t correct_count = 0;
size_t all_count = 0;
size_t start_index = 0;
while (start_index < val_num) {
if (start_index + batch_size > val_num) {
start_index = val_num - batch_size;
}
args_map["data"] =
val_data.Slice(start_index, start_index + batch_size).Copy(ctx_dev);
args_map["data_label"] =
val_label.Slice(start_index, start_index + batch_size).Copy(ctx_dev);
start_index += batch_size;
NDArray::WaitAll();
Executor *exe = lenet.SimpleBind(ctx_dev, args_map);
exe->Forward(false);
const auto &out = exe->outputs;
NDArray out_cpu = out[0].Copy(ctx_cpu);
NDArray label_cpu =
val_label.Slice(start_index - batch_size, start_index).Copy(ctx_cpu);
NDArray::WaitAll();
const mx_float *dptr_label = label_cpu.GetData();
float *dptr = new float[120000];
float *dptr1 = new float[40000];
NDArray save_cpu = out_cpu.Copy(ctx_cpu);
NDArray::WaitAll();
save_cpu.SyncCopyToCPU(dptr, 120000);
//判断每个像素点的类别
for (int i = 0; i < 40000;i++)
{
float p = 0;
if (dptr[i + 40000] > dptr[i])
{
p = 1;
if (dptr[i + 80000] > dptr[i + 40000])
p = 2;
}
else
if (dptr[i + 80000] > dptr[i])
p = 2;
dptr1[i] = p;
}
for (int i = 0; i < 40000; i++)
{
if (dptr1[i] == dptr_label[i])
correct_count++;
}
all_count +=40000;
delete exe;
}
return correct_count * 1.0 / all_count;
}
};
int main(int argc, char const *argv[]) {
Lenet lenet;
lenet.Run();
return 0;
}
This is the image file i use to test.
![1](https://cloud.githubusercontent.com/assets/15666683/14096752/a9b10534-f59d-11e5-9fa0-b0d573132869.jpg)
![1](https://cloud.githubusercontent.com/assets/15666683/14096751/a9aff75c-f59d-11e5-9e9a-6f87706b4351.png)