机器学习应用到Android开发的探索

背景:

个人认为机器学习、深度学习就在身边,从不遥远,如何让Android开发和常规的机器学习结合起来使用?这里分享一些摸索的过程。

基础资源

机器学习入门,推荐吴恩达的课程Supervised Learning in Machine Learning: Regression and Classification (DeepLearning.AI) | Coursera,以及西瓜书等系列书籍。

目前比较热门的GitHub资源:

NCNN,https://github.com/Tencent/ncnn  (见详细配置教程,以及自定义模型训练)

Deeplearning4j,适合Java工程师等使用的深度学习框架,  GitHub - deeplearning4j/deeplearning4j: Suite of tools for deploying and training deep learning models using the JVM. Highlights include model import for keras, tensorflow, and onnx/pytorch, a modular and tiny c++ library for running math code and a java based math library on top of the core c++ library. Also includes samediff: a pytorch/tensorflow like library for running deep learning using automatic differentiation.

目录

Part01:《环境配置》

Part02:《C语言和MATLAB混编》

Part03:《Java语言和MATLAB混编》

Part01:《环境配置》

一、Windows环境(win7,VS2017+MATLAB_R2016b_x64)

1、在VS添加必要环境设置

链接文件:libmx.lib,libmex.lib和libmat.lib (位于MATLAB库目录);

头文件:engine.h,matrix.h,tmwtypes.h(位于MATLAB包含目录)

包含目录:D:\MATLAB\R2016b\extern\include;

库目录:

D:\ProgramFiles (x86)\SetupDir\MATLAB\R2016b\extern\lib\win64\microsoft;

D:\ProgramFiles (x86)\SetupDir\MATLAB\R2016b\extern\lib\win64\mingw64;

附加器目录: D:\ProgramFiles (x86)\SetupDir\MATLAB\R2016b\bin\win64; (可不加)

二、Linux环境(Centos7.5,gcc-7.3.0+matlab_R2016b_x64)

1、必要环境设置(matlab默认安装情况下)

链接文件:libmx.so,libmex.so和libmat.so

头文件:engine.h,matrix.h,tmwtypes.h

包含目录:/usr/local/MATLAB/R2016b/extern/include

库目录:/usr/local/MATLAB/R2016b/bin/glnxa64

2、 matlab引擎依赖条件

  ①matlab引擎依赖/bin/csh启动,所以不管你使用何种shell,都必须安装csh

  #yum install chs    (centos/redhat平台)

②gcc版本过低,会出现链接库的问题(经测试,6.1.0版本gcc也是可以的)

Part02:《C语言和MATLAB混编》

官方文档介绍

Type for MATLAB engine - MATLAB- MathWorks 中国

编写 C 程序以读取 MAT 文件数据- MATLAB & Simulink- MathWorks 中国

ps:这里为什么使用C语言和MATLAB混编?不仅因为MATLAB是一款功能非常强大的软件,而且支持C语言、JAVA语言等主流语言,可以直接将算法文件(.m类型)生成jar包,引用到Android开发中

一、C语言调用MATLAB示例

        简单来说,本示例实现的是使用MATLAB编写一段数据处理的算法,生成m文件;在本地或者云服务器通过C语言调用MATLAB,执行算法文件,返回数据结果(如自行购买配置阿里云服务器,可从云端直接返回结果到客户端,达成联动)。(这里涉及C语言调用MATLAB混编的过程,纯属踩坑过程,记录备案)

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "engine.h"
#include "matrix.h"
#define  BUFSIZE 256
#define  N 120
int main()
{
    //定义MATLAB Engine 
	Engine *ep;  

 	//定义缓存空间,提取结果									
	char level,buffer[BUFSIZE + 1];
	int i=25,num;
    
    //定义MATLAB C函数库参数
	mxArray *testdata = NULL, *result = NULL;

    //这里自定义数组样例,可以使用data.mat导入
	double cArray[N] = { 
		0	,	4	,	10	,	1	,1	,	7	,	15	,	1	,1	,	11	,	12	,	1	,
		1	,	23	,	14	,	1	,1	,	25	,	18	,	1	,1	,	26	,	14	,	1	,
		1	,	39	,	26	,	1	,1	,	36	,	36	,	1	,1	,	26	,	42	,	1	,
		1	,	39	,	36	,	1	,1	,	38	,	31	,	2	,1	,	36	,	35	,	2	,
		1	,	36	,	35	,	2	,1	,	48	,	31	,	1	,1	,	39	,	22	,	1	,
		1	,	17	,	11	,	1	,1	,	33	,	13	,	1	,2	,	65	,	9	,	1	,
		2	,	50	,	17	,	1	,2	,	74	,	10	,	1	,1	,	51	,	44	,	1	,
		1	,	28	,	62	,	1	,1	,	17	,	37	,	1	,1	,	7	,	21	,	2	,
		1	,	6	,	12	,	1	,1	,	24	,	12	,	1	,1	,	39	,	16	,	1	,
		2	,	49	,	13	,	1	,1	,	29	,	30	,	1	,1	,	24	,	33	,	2
	};

    //windows环境下,不用指定路径将engOpen的参数改为engOpen(NULL) 
    //使用engOpen("path")命令打开软件
	if (!(ep = engOpen("/usr/local/MATLAB/R2016b/bin/matlab")))
	{
		printf("Can't start MATLAB engine!");
		return EXIT_FAILURE;
	}

    //设置MATLAB无界面运行
	engSetVisible(ep,false);

    //创建矩阵
	testdata = mxCreateDoubleMatrix(1, N, mxREAL);										

    //拷贝数组
	memcpy((double *)mxGetPr(testdata), (double *)cArray, N * sizeof(double));

        //传递数据到MATLAB环境
        if(engPutVariable(ep, "input_data", testdata) == 1){
		    printf("Failed to send  testdata to MATLAB !");	
        }

    //传递指令,在MATLAB保存数据文件data.mat
	engEvalString(ep, "save data.mat 'input_data';");
	buffer[BUFSIZE] = '\0';

    //指定缓存区
	engOutputBuffer(ep, buffer, BUFSIZE);

    //执行m文件			
	engEvalString(ep, "MTest");		

    //关闭缓存	           
	engOutputBuffer(ep, NULL, 0);					

    //从工作区提取变量
	if ((result = engGetVariable(ep, "num")) == NULL)
		printf("The  result of MATLAB is %s.\n", buffer);								
		for(;!(buffer[i]>='A' && buffer[i]<='Z');i++){
		  if(buffer[i]>='0' && buffer[i]<='9')
			return_num=(int)(buffer[i]-48);
		}
		level=(char)buffer[i];
		printf("The return_num is %d\n\n",num);	//结果返回
		printf("The level is %c\n\n",level);		                
	}
	else{
		 printf("There is something wrong with MTest.m!Check again!\n" );
	}

    //释放内存
	mxDestroyArray(testdata);				                
	mxDestroyArray(result);

    //关闭软件										
	engClose(ep);						                    
	return EXIT_SUCCESS;
}

二、数据处理demo(MATLAB语言)

本示例代码实现的功能:在c语言里面往MATLAB传送一组数据,并输入指令调用MTest.m进行处理,得到返回结果kind和level(4x5维)。

文件说明:

data.mat:数据文件,1x120维;

net.m:自设计BP神经网络模型

clc
clear
load net ;

%***************************
%提取输入矩阵
%预处理
%***************************

TEMP = load( 'data.mat');
tmp = struct2cell(TEMP);
tmp=char(tmp);
row=size(tmp,1);
string=[];
target=[];
string=tmp;

col=size(string,2);
ch1=string(1:8:col);
ch2=string(2:8:col);
ch3=string(3:8:col);
ch4=string(4:8:col);
ch5=string(5:8:col);
ch6=string(6:8:col);
ch7=string(7:8:col);
ch8=string(8:8:col);
str1=[ch1',ch2'];
str2=[ch3',ch4'];
str3=[ch5',ch6'];
str4=[ch7',ch8'];
col1=smooth(hex2dec(str1),30);
col2=smooth(hex2dec(str2),30);
col3=smooth(hex2dec(str3),30);
col4=smooth(hex2dec(str4),30);
initdata=[col1 col2 col3 col4];

%按行列提取数据,阈值150
[row,col]=size(initdata);
yan=0;
for i=1:1:row
    if initdata(i,4)>=150
        yan=1;
    end
end
if yan==1 && mean(initdata(:,2))>=10
    kind='0x01';
else
    if  (mean(initdata(:,2))<18 & mean(initdata(:,1))<8 & mean(initdata(:,3))<10 )  
        target=1;
        up=2;
    elseif (mean(initdata(1:15,1))>=mean(initdata(16:30,1)) & (mean(initdata(1:15,2))>mean(initdata(16:30,2))) &  (mean(initdata(:,2))>mean(initdata(:,1))) )
        target=2;
    else
        target=0;
    end

%     xs
   if mean(initdata(:,1))>2.5*mean(initdata(:,2))
    for i=1:1:row
     initdata(i,3)=10;
     initdata(i,2)=10;
    end
  end
   
%    xj
if mean(initdata(:,1))>160
       for i=1:1:row
        initdata(i,2)=10;
        initdata(i,3)=10;
       end
end
 if (mean(initdata(:,2))>3*mean(initdata(:,1))) && mean(initdata(:,2))>3*mean(initdata(:,3))
       for i=1:1:row
         initdata(i,1)=16;
         initdata(i,2)=initdata(i,2)+10;
        end
 end
   
    if (mean(initdata(:,2))+mean(initdata(:,3)))>2*mean(initdata(:,1))
     for i=1:1:row
         initdata(i,1)=10;
     end
    end

    % 预处理
    temp1=initdata(1:10,1:3);
    temp2=initdata(11:20,1:3);
    temp3=initdata(21:30,1:3);
    input_data1=[mean(temp1),mean(temp1(:,1)-temp1(:,2)),mean(temp1(:,1)-temp1(:,3))]';
    input_data2=[mean(temp2),mean(temp2(:,1)-temp2(:,2)),mean(temp2(:,1)-temp2(:,3))]';
    input_data3=[mean(temp3),mean(temp3(:,1)-temp3(:,2)),mean(temp3(:,1)-temp3(:,3))]';
 
% 仿真
    y11=sim(net14,input_data1);
    y21=sim(net24,input_data1);
    y31=sim(net34,input_data1);
    y41=sim(net44,input_data1);
    y51=sim(net54,input_data1);
    
    y12=sim(net14,input_data2);
    y22=sim(net24,input_data2);
    y32=sim(net34,input_data2);
    y42=sim(net44,input_data2);
    y52=sim(net54,input_data2);
    
    y13=sim(net14,input_data3);
    y23=sim(net24,input_data3);
    y33=sim(net34,input_data3);
    y43=sim(net44,input_data3);
    y53=sim(net54,input_data3);
    
    [~,kind11]=max(y11);
    [~,kind21]=max(y21);
    [~,kind31]=max(y31);
    [~,kind41]=max(y41);
    [~,kind51]=max(y51);

    [~,kind12]=max(y12);
    [~,kind22]=max(y22);
    [~,kind32]=max(y32);
    [~,kind42]=max(y42);
    [~,kind52]=max(y52);
    
    [~,kind13]=max(y13);
    [~,kind23]=max(y23);
    [~,kind33]=max(y33);
    [~,kind43]=max(y43);
    [~,kind53]=max(y53);

% 投票
    kq=0;
    xs=0;
    jp=0;
    cz=0;
    yq=0;
    kind_select1=[kind11;kind21;kind31;kind41;kind51];
    kind_select2=[kind12;kind22;kind32;kind42;kind52];
    kind_select3=[kind13;kind23;kind33;kind43;kind53];
    for j=1:1:size(kind_select1,1)
        if kind_select1(j)==3
            xs=xs+1;
        elseif kind_select1(j)==2
            jp=jp+1;
         elseif kind_select1(j)==2
             cz=cz+1;
        elseif kind_select1(j)==1
            yq=yq+1;
        else
            kq=kq+1;
        end
    end
    for j=1:1:size(kind_select2,1)
        if kind_select2(j)==3
            xs=xs+1;
        elseif kind_select2(j)==2
            jp=jp+1;
         elseif kind_select2(j)==2
             cz=cz+1;
        elseif kind_select2(j)==1
            yq=yq+1;
        else
            kq=kq+1;
        end
    end
    for j=1:1:size(kind_select3,1)
        if kind_select3(j)==3
            xs=xs+1;
        elseif kind_select3(j)==2
            jp=jp+1;
         elseif kind_select3(j)==2
             cz=cz+1;
        elseif kind_select3(j)==1
            yq=yq+1;
        else
            kq=kq+1;
        end
    end
        [~,kind_num]=max([xs,jp,yq]);
        if xs==0 & jp==0 & yq==0
            target=1;
        end

%结果转化
if target==1
   kind='0x00';
elseif target==2
    load temp kind;
else
if kind_num==1
    kind='0x02';
elseif kind_num==2
    kind='0x03';
elseif kind_num==3
    kind='0x04';
elseif kind_num==4
     kind='0x04';
else
    kind='0x00';
end

end
end
if (kind=='0x02'| kind=='0x03' | kind=='0x04' )& up~=0
    kind='0x00';
    up=up-1;
end
% 浓度分级
data=mean(initdata);

if strcmp(kind,'0x00')
    level='0x01';
elseif strcmp(kind,'0x01')
    if data(1,4)>=270
        level='0x05';
    elseif data(1,4)>=230
        level='0x04';
    elseif data(1,4)>=190
        level='0x03';
    elseif data(1,4)>=150
        level='0x02';
    else
        level='0x01';
    end

elseif strcmp(kind,'0x02')
    if data(1,1)>=150
        level='0x05';
    elseif data(1,1)>=100
        level='0x04';
    elseif data(1,1)>=50
        level='0x03';
    elseif data(1,1)>=20
        level='0x02';
    else
        level='0x01';
    end

elseif strcmp(kind,'0x03')
    if data(1,2)>=40
        level='0x05';
    elseif data(1,2)>=30
        level='0x04';
    elseif data(1,2)>=20
        level='0x03';
    elseif data(1,2)>=10
        level='0x02';
    else
        level='0x01';
    end

elseif strcmp(kind,'0x04')
    if data(1,2)>=40
        level='0x05';
    elseif data(1,2)>=30
        level='0x04';
    elseif data(1,2)>=20
        level='0x03';
    elseif data(1,2)>=10
        level='0x02';
    else
        level='0x01';
    end

else
    level='0x00';        
end

//保存变量,打印结果
save temp kind up
kind
level

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值