cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
sayanseth
Visitor
Visitor
662 Views
Registered: ‎12-20-2018

Less accuracy of Caffe MNIST LeNet when running on DPU

Board: ZCU104

DNNDK Version: v3.0

Attachment :

1. deploy.prototxt

2. main.cc

Dataset : MNIST

Network: LeNet

 

Accuracy in Computer 97.2% but in Board 86.85%

Problem is in our caffe model there is no mean value is provided.

we supplied the mean value using dpuSetInputImage function.

Caffe compute_image_mean function giving mean value 33.3184 which is giving accuracy <1%

After some trial and error method using different mean values we found 0.102 gives maximum accuracy.

What can we do to increase accuracy and how to calculate accurate mean value?

[DPU IP Spec]
IP  Timestamp   : 2019-04-18 15:30:00
DPU Core Count  : 2

[DPU Core List]
DPU Core        : #0
DPU Enabled     : Yes
DPU Arch        : B4096F
DPU Target      : v1.4.0
DPU Freqency    : 333 MHz
DPU Features    : Avg-Pooling, LeakyReLU/ReLU6, Depthwise Conv
DPU Core        : #1
DPU Enabled     : Yes
DPU Arch        : B4096F
DPU Target      : v1.4.0
DPU Freqency    : 333 MHz
DPU Features    : Avg-Pooling, LeakyReLU/ReLU6, Depthwise Conv
layer {
  name: "mnist"
  type: "Input"
  top: "data"
  transform_param {
    scale: 0.00390625
  }
  input_param {
    shape {
      dim: 1
      dim: 1
      dim: 28
      dim: 28
    }
  }
}
layer {
  name: "conv1"
  type: "Convolution"
  bottom: "data"
  top: "conv1"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  phase: TRAIN
  convolution_param {
    num_output: 20
    kernel_size: 5
    stride: 1
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "pool1"
  type: "Pooling"
  bottom: "conv1"
  top: "pool1"
  phase: TRAIN
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layer {
  name: "conv2"
  type: "Convolution"
  bottom: "pool1"
  top: "conv2"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  phase: TRAIN
  convolution_param {
    num_output: 50
    kernel_size: 5
    stride: 1
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "pool2"
  type: "Pooling"
  bottom: "conv2"
  top: "pool2"
  phase: TRAIN
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layer {
  name: "ip1"
  type: "InnerProduct"
  bottom: "pool2"
  top: "ip1"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  phase: TRAIN
  inner_product_param {
    num_output: 500
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "relu1"
  type: "ReLU"
  bottom: "ip1"
  top: "ip1"
  phase: TRAIN
}
layer {
  name: "ip2"
  type: "InnerProduct"
  bottom: "ip1"
  top: "ip2"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  phase: TRAIN
  inner_product_param {
    num_output: 10
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "loss"
  type: "Softmax"
  bottom: "ip2"
  top: "loss"
  loss_weight: 1
  phase: TRAIN
}
#include <assert.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <queue>
#include <string>
#include <vector>
#include <string>
#include <stdint.h>

/* header file OpenCV for image processing */
#include <opencv2/opencv.hpp>

/* header file for DNNDK APIs */
#include <dnndk/dnndk.h>

using namespace std;
using namespace cv;


//Finds max elements in the softmax array and returns its index, i.e. the result
int find_result(const float *d, int size)
{
	vector<float> v;
	vector<float>::iterator result;
	for ( auto i = 0; i < size; ++i )
	{
		v.push_back( d[ i ]);
	}

	result = max_element( v.begin(), v.end() );
	int answer = distance( v.begin(), result );

	return answer;
}

//Should be self explanatory
void read_labels( int* labels, string label_path, int number_of_samples )
{
    int cnt = 0;
    string token;
    ifstream infile( label_path );
	while(infile >> token)
	{
        
		labels[ cnt ] = stoi( token );
		cnt++;
		if( cnt > number_of_samples )
		{
			break;
		}
        
	}
}

void runMNIST( DPUTask *conv_task )
{

	assert( conv_task );

	//Enter mean value of input channel(s) and the pointer to that. Required as dpuSetInputImage2 doesn't work.
	float mean = 0.102;
	float* mean_pt = &mean;

	//Storing number of test cases.
	int number_of_samples = 10000;

	//Test label file path goes here.
	string label_path = "/root/Desktop/lenet_board/test_labels/labels.txt";

	//Create and read test label array from test label file path.
    int* labels = new int[ number_of_samples ];
    read_labels( labels, label_path, number_of_samples );

	//Iniitializing accuracy counter.
	int right_answer = 0;

	//Test image files path goes here.
	string image_path = "/root/Desktop/lenet_board/test_images/x_test_";

	//Initializing confusion matrix here. Rows are the results we got. Colums are the labels.
	int confusion_matrix[ 10 ][ 10 ];
	for ( auto i = 0; i < 10; ++i )
	{
		for( auto j = 0; j < 10; ++j )
		{
			confusion_matrix[ i ][ j ] = 0;
		}
	}

	//For test runs.
	int batch_no = 1;
	int num_classes = 10;

	//Entering the loop
	for ( int counter = 0; counter < number_of_samples; ++counter )
	{
		string image_name = image_path + to_string( counter ) + ".png";
		Mat image = imread( image_name.c_str(),0);

		if ( image.empty() )
		{
			return;
		}
	    
		//Entering input image into kernel input node
		dpuSetInputImage( conv_task, "conv1", image, mean_pt );

		//Invoke the kernel
		dpuRunTask(conv_task);

		////Get the output tensor from the kernel output node
		DPUTensor *outTensor = dpuGetOutputTensor( conv_task, "ip2" );

		float output_scale = dpuGetTensorScale( outTensor );
		int tensorSize = dpuGetTensorSize( outTensor );

		int8_t* logits = new int8_t[ tensorSize ];	
		dpuGetOutputTensorInHWCInt8( conv_task, "ip2", logits, tensorSize );

		float* softmax = new float[ tensorSize ];
		dpuRunSoftmax(logits, softmax, num_classes, batch_no, output_scale);

		//Find result from the softmax array
		int res = find_result( softmax, 10);

		if ( res == labels[ counter ] )
		{
			//Got the right answer
			right_answer++;
			
		}

		//Increment the confusion matrix element
		confusion_matrix[ res ][ labels[ counter ] ] += 1;

		//Flush the allocated memory for arrays
		delete[] logits;
		delete[] softmax;

	}
	
	float accuracy = float(right_answer) / float( number_of_samples );
	cout << "Accuracy    " << accuracy << endl;

	//Printing the confusion matrix here
	int check = 0; //for debug
	for ( auto i = 0; i < 10; ++i )
	{
		for( auto j = 0; j < 10; ++j )
		{
			cout << confusion_matrix[ i ][ j ] <<"\t\t  ";
			check += confusion_matrix[ i ][ j ];
		}
		cout << " " << endl;
		cout << " " << endl;
		cout << " " << endl;
		cout << " " << endl;
	}
	cout << check << endl;

}


int main ( void )
{
	 //Initialize the DPU kernel and the DPU task for it
	DPUKernel *conv_kernel;
	DPUTask *conv_task;

	//Open the DPU device
	dpuOpen();

	//Must put the kernel name found in the .info file created after DNNC compilation
	conv_kernel = dpuLoadKernel( "lenet_0" );
	conv_task = dpuCreateTask( conv_kernel, 0 );

	//Self explanatory
	runMNIST( conv_task );

	//Destroy the task first and then the kernel
	dpuDestroyTask( conv_task );
	dpuDestroyKernel( conv_kernel );

	//Close the DPU device after work is done
	dpuClose();

	return 0;

}

 

0 Kudos
0 Replies