在Android Studio里撰写Python程序

by高焕堂

1. 首先建立一个Android项目

首先建立一个新的Android程序开发项目。

599835-20200717202857813-1392121270.png

例如,档案名称是—myHello.py。

599835-20200717202941259-902480956.png

并且开始撰写Python程序:

599835-20200717203038982-204377978.png

其完整程序如下:

# myHello.py

import numpy as np

from java import jclass

def sigmoid(x):

return 1/(1+np.exp(-x))

def softmax(x):

orig_shape=x.shape

if len(x.shape)>1:

#Matrix

tmp=np.max(x,axis=1)

x-=tmp.reshape((x.shape[0],1))

x=np.exp(x)

tmp=np.sum(x,axis=1)

x/=tmp.reshape((x.shape[0],1))

else:

#Vector

tmp=np.max(x)

x-=tmp

x=np.exp(x)

tmp=np.sum(x)

x/=tmp

return x

hidden_nodes = 3

output_labels = 2

dx = np. array([[7.5, 5.5], [3, 12.5], [6.6, 3.5], [1.2, 7.5]],

dtype=np.float32)

test_x = np. array( [[2.8, 5.9], [4.8, 3.3]], dtype=np.float32)

dt = np. array([[1,0], [0,1], [1,0], [0,1]],dtype=np.float32)

wh = np. array([[0.1, 0.5, 0.1],

[0.1, 0.5, 0.1]], dtype=np.float32)

bh = np.array([0.5, 0.5, 0.5], dtype=np.float32)

wo = np. array([[0.1, 0.5], [0.5, 0.5], [0.5, 0.1]], dtype=np.float32)

bo = np.array([0.5, 0.5], dtype=np.float32)

lr = 0.05

yv = 0

def one_round(x, t):

global wh, bh, wo, bo, lr, yv

#----- 开始训练 -----------------------

#feedforward

yh = np.dot(x, wh) + bh

zh = sigmoid(yh)

yo = np.dot(zh, wo) + bo

zo = softmax(yo)

# BP for Output ---------------------

error = t - zo

delta = lr * error

error_h = np.dot(delta , wo.T)

dw_o = np.zeros((3, 2), np.float32)

for i in range(3):

for j in range(2):

dw_o[i, j] = zh[i] * delta[j]

db_o = delta

# BP for Hidden

delta_h = zh * (1-zh) * error_h

dw_h = np.zeros((2, 3), np.float32)

for i in range(2):

for j in range(3):

dw_h[i, j] = x[i] * delta_h[j]

db_h = delta_h

# Update Weights

wh += dw_h

bh += db_h

wo += dw_o

bo += db_o

yv += 1

#------------------------------------

def train(ep):

global wh, bh, wo, bo, lr, yv

for k in range(100):

for i in range(4):

one_round(dx[i], dt[i])

return yv

#----- Predict ------------------------

def predict(x):

global wh, bh, wo, bo, lr, yv, test_x

yh = np.dot(test_x, wh) + bh

zh = sigmoid(yh)

yo = np.dot(zh, wo) + bo

zo = softmax(yo)

pv = np.round(zo, 5)

return pv

# END

2.上述Python程式码的说明

这是一个二元分类的范例。其中有2只<玩具兔>和2只<玩具猫>。其中,主要的特征在于兔子是:耳朵长、尾巴短;而猫则是:尾巴长、耳朵短。其资料如下:

599835-20200717203539412-1481256180.png

※ 正向推演(Feed-Forward)阶段

上述Python程式,建立了一个两层的NN模型(含有一个隐藏层):

599835-20200717203630666-1899182789.png

其中,权重(W)则代表讯息传递的强弱。然后,需要使用到不同的数学式来计算各个y值(包括y0、y1、y2、y3),这些数学式,就如下图所示:

599835-20200717203717160-1882335296.png

所谓正向推演部分,就是将x0和x1训练资料喂给(Feed)这NN模型的输入层,然后透过上图的数学式的计算,推演出下一层(即隐藏层)的y0、y1和y2。,基于这些y[]值、计算出z[]值,再透过数学式的计算,推演到下一层(即输出层)的 z3值。

※ 反向传播(Back-Propagation)阶段

经由刚才的正向推演计算,得到了输出层的z3值之后,就可以展开反向传播的运算了。首先计算落差值(t-z3),再从这落差值计算出<反向修正值(Delta)>,如下图:

599835-20200717203806330-1100107659.png

然后,拿这反向修正(Delta)值来与w03相乘,就反向推演出隐藏层第#0神经元(即y0)的误差值了。如下图:

599835-20200717203851911-487005556.png

同样地,拿这delta值来与w13相乘,就反向推演出隐藏层y1神经元的误差值了。如下图:

599835-20200717203954233-163601721.png

同样地,拿这delta值来与w13相乘,就反向推演出隐藏层y2神经元的误差值了。如下图:

599835-20200717204033637-1326218662.png

到此已经反向推演出隐藏层的各神经元的落差值:loss_y0、loss_y1和loss_y2值了。接下来,就依据落差值来计算出修正值:delta_y0、delta_y1和delta_y2值。以便修正各相关的权重(Weight)值了。例如,从loss_y0计算出delta_y0,继续藉由delta_y0来修正w00和w10值,来提升这NN模型的智慧,如下图:

599835-20200717204112204-1821249507.png

同样地,也从loss_y1计算出delta_y1,继续藉由delta_y1来修正w01和w11的值。一样地,也从loss_y2计算出delta_y2,继续藉由delta_y2来修正w02和w12的值,来记录NN模型的智慧,如下图:

599835-20200717204207042-1754022826.png

最后,依据输出层的delta值来修正输出层的权重(Weight)如下图:

599835-20200717204305419-1739999848.png

于是,完成了这个2层AI模型的训练了。

3.开发Java程式:定义UI

开始以Java设计UI部分,兹修改myActivity.java如下:

599835-20200717204339789-961611706.png

其完整程序如下:

#myActivity.java

package com.example.chaquo01;

import android.os.Bundle;

import android.support.v7.app.AppCompatActivity;

import android.widget.TextView;

import java.util.List;

import com.chaquo.python.android.AndroidPlatform;

import com.chaquo.python.*;

public class myActivity extends AppCompatActivity {

TextView tv1, tv2, tv3, tv4, tv5, tv6;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

tv1 = (TextView) findViewById(R.id.tv_device);

tv2 = (TextView) findViewById(R.id.tv_device2);

tv3 = (TextView) findViewById(R.id.tv_device3);

tv4 = (TextView) findViewById(R.id.tv_device4);

tv5 = (TextView) findViewById(R.id.tv_device5);

tv6 = (TextView) findViewById(R.id.tv_device6);

tv2.setText(" ....... Prediction .......");

//-------------------------------------------------------------------------

if (!Python.isStarted()) {

Python.start(new AndroidPlatform(this));

}

//------- 呼叫 Python(myHello)程式里的函数:mul_add()

Python py = Python.getInstance();

PyObject obj1 = py.getModule("myHello").callAttr("train", 1000);

PyObject obj2 =

py.getModule("myHello").callAttr("predict", 1000);

List pyList = obj2.asList();

String ss1 = pyList.get(0).toString();

String ss2 = pyList.get(1).toString();

tv3.setText(" ["+ss1);

tv4.setText(" "+ss2 + "]");

}}

4.执行这个Android App程序

执行这个Android App程序,它首先启动myActivity.java。执行到指令:

PyObject obj1 = py.getModule("myHello").callAttr("train", 1000);

就呼叫myHello.py的train()函数。进行AI模型的训练。训练好了,就执行到指令:

PyObject obj2 = py.getModule("myHello").callAttr("predict", 1000);

就呼叫myHello.py的predicyt()函数,进行预测的任务。然后,输出预测的结果,如下图所示:

599835-20200717204640929-670413275.png

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐