CMSIS-DSP: Added an SVM example to show how to use it.
parent
665ba5d4cb
commit
585137ad16
@ -0,0 +1,45 @@
|
|||||||
|
cmake_minimum_required (VERSION 3.6)
|
||||||
|
project (arm_svm_example VERSION 0.1)
|
||||||
|
|
||||||
|
|
||||||
|
# Needed to include the configBoot module
|
||||||
|
# Define the path to CMSIS-DSP (ROOT is defined on command line when using cmake)
|
||||||
|
set(ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../../../..)
|
||||||
|
set(DSP ${ROOT}/CMSIS/DSP)
|
||||||
|
|
||||||
|
# Add DSP folder to module path
|
||||||
|
list(APPEND CMAKE_MODULE_PATH ${DSP})
|
||||||
|
|
||||||
|
###################################
|
||||||
|
#
|
||||||
|
# LIBRARIES
|
||||||
|
#
|
||||||
|
###################################
|
||||||
|
|
||||||
|
###########
|
||||||
|
#
|
||||||
|
# CMSIS DSP
|
||||||
|
#
|
||||||
|
|
||||||
|
add_subdirectory(../../../Source bin_dsp)
|
||||||
|
|
||||||
|
|
||||||
|
###################################
|
||||||
|
#
|
||||||
|
# TEST APPLICATION
|
||||||
|
#
|
||||||
|
###################################
|
||||||
|
|
||||||
|
|
||||||
|
add_executable(arm_svm_example)
|
||||||
|
|
||||||
|
|
||||||
|
include(config)
|
||||||
|
configApp(arm_svm_example ${ROOT})
|
||||||
|
|
||||||
|
target_sources(arm_svm_example PRIVATE arm_svm_example_f32.c)
|
||||||
|
|
||||||
|
### Sources and libs
|
||||||
|
|
||||||
|
target_link_libraries(arm_svm_example PRIVATE CMSISDSP)
|
||||||
|
|
||||||
@ -0,0 +1,185 @@
|
|||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
* Copyright (C) 2019-2020 ARM Limited. All rights reserved.
|
||||||
|
*
|
||||||
|
* $Date: 09. December 2019
|
||||||
|
* $Revision: V1.0.0
|
||||||
|
*
|
||||||
|
* Project: CMSIS DSP Library
|
||||||
|
* Title: arm_svm_example_f32.c
|
||||||
|
*
|
||||||
|
* Description: Example code demonstrating how to use SVM functions.
|
||||||
|
*
|
||||||
|
* Target Processor: Cortex-M/Cortex-A
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* - Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* - Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* - Neither the name of ARM LIMITED nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
* -------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup groupExamples
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup SVMExample SVM Example
|
||||||
|
*
|
||||||
|
* \par Description:
|
||||||
|
* \par
|
||||||
|
* Demonstrates the use of SVM functions. It is complementing the tutorial
|
||||||
|
* about classical ML with CMSIS-DSP and python scikit-learn.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/** \example arm_svm_example_f32.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "arm_math.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
The polynomial SVM instance containing all parameters.
|
||||||
|
Those parameters can be generated with the python library scikit-learn.
|
||||||
|
|
||||||
|
*/
|
||||||
|
arm_svm_polynomial_instance_f32 params;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Parameters generated by a training of the SVM classifier
|
||||||
|
using scikit-learn and some random input data.
|
||||||
|
|
||||||
|
*/
|
||||||
|
#define NB_SUPPORT_VECTORS 11
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Dimension of the vector space. A vector is your feature.
|
||||||
|
It could, for instance, be the pixels of a picture or
|
||||||
|
the FFT of a signal.
|
||||||
|
|
||||||
|
*/
|
||||||
|
#define VECTOR_DIMENSION 2
|
||||||
|
|
||||||
|
const float32_t dualCoefficients[NB_SUPPORT_VECTORS]={-0.01628988f, -0.0971605f,
|
||||||
|
-0.02707579f, 0.0249406f, 0.00223095f, 0.04117345f,
|
||||||
|
0.0262687f, 0.00800358f, 0.00581823f, 0.02346904f, 0.00862162f}; /* Dual coefficients */
|
||||||
|
|
||||||
|
const float32_t supportVectors[NB_SUPPORT_VECTORS*VECTOR_DIMENSION]={ 1.2510991f, 0.47782799f,
|
||||||
|
-0.32711859f, -1.49880648f, -0.08905047f, 1.31907242f,
|
||||||
|
1.14059333f, 2.63443767f, -2.62561524f, 1.02120701f,
|
||||||
|
-1.2361353f, -2.53145187f,
|
||||||
|
2.28308122f, -1.58185875f, 2.73955981f, 0.35759327f,
|
||||||
|
0.56662986f, 2.79702016f,
|
||||||
|
-2.51380816f, 1.29295364f, -0.56658669f, -2.81944734f}; /* Support vectors */
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Class A is identified with value 0.
|
||||||
|
Class B is identified with value 1.
|
||||||
|
|
||||||
|
This array is used by the SVM functions to do a conversion
|
||||||
|
and ease the comparison with the Python code where
|
||||||
|
different values could be used.
|
||||||
|
|
||||||
|
*/
|
||||||
|
const int32_t classes[2]={0,1};
|
||||||
|
|
||||||
|
|
||||||
|
int32_t main(void)
|
||||||
|
{
|
||||||
|
/* Array of input data */
|
||||||
|
float32_t in[VECTOR_DIMENSION];
|
||||||
|
|
||||||
|
/* Result of the classifier */
|
||||||
|
int32_t result;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Initialization of the SVM instance parameters.
|
||||||
|
|
||||||
|
Additional parameters (intercept, degree, coef0 and gamma)
|
||||||
|
are also coming from Python.
|
||||||
|
|
||||||
|
*/
|
||||||
|
arm_svm_polynomial_init_f32(¶ms,
|
||||||
|
NB_SUPPORT_VECTORS,
|
||||||
|
VECTOR_DIMENSION,
|
||||||
|
-1.661719f, /* Intercept */
|
||||||
|
dualCoefficients,
|
||||||
|
supportVectors,
|
||||||
|
classes,
|
||||||
|
3, /* degree */
|
||||||
|
1.100000f, /* Coef0 */
|
||||||
|
0.500000f /* Gamma */
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Input data. It is corresponding to a point inside
|
||||||
|
the first class.
|
||||||
|
|
||||||
|
*/
|
||||||
|
in[0] = 0.4f;
|
||||||
|
in[1] = 0.1f;
|
||||||
|
arm_svm_polynomial_predict_f32(¶ms,
|
||||||
|
in,
|
||||||
|
&result);
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Result should be 0 : First class
|
||||||
|
|
||||||
|
*/
|
||||||
|
printf("Result = %d\n", result);
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This input vector is corresponding to a point inside
|
||||||
|
the second class.
|
||||||
|
|
||||||
|
*/
|
||||||
|
in[0] = 3.0f;
|
||||||
|
in[1] = 0.0f;
|
||||||
|
arm_svm_polynomial_predict_f32(¶ms,
|
||||||
|
in,
|
||||||
|
&result);
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Result should be 1 : Second class
|
||||||
|
|
||||||
|
*/
|
||||||
|
printf("Result = %d\n", result);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,110 @@
|
|||||||
|
from sklearn import svm
|
||||||
|
import random
|
||||||
|
import numpy as np
|
||||||
|
import math
|
||||||
|
|
||||||
|
from pylab import scatter,figure, clf, plot, xlabel, ylabel, xlim, ylim, title, grid, axes, show,semilogx, semilogy
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from matplotlib.ticker import MaxNLocator
|
||||||
|
from matplotlib.colors import BoundaryNorm
|
||||||
|
|
||||||
|
# Generation of data to train the SVM classifier
|
||||||
|
# 100 vectors are generated. Vector have dimension 2 so can be represented as points
|
||||||
|
NBVECS = 100
|
||||||
|
VECDIM = 2
|
||||||
|
|
||||||
|
# A cluster of point is generated around the origin.
|
||||||
|
ballRadius = 0.5
|
||||||
|
x = ballRadius * np.random.randn(NBVECS,2)
|
||||||
|
|
||||||
|
# An annulus of point is generated around the central cluster.
|
||||||
|
angle = 2.0*math.pi * np.random.randn(1,NBVECS)
|
||||||
|
radius = 3.0+0.1*np.random.randn(1,NBVECS)
|
||||||
|
|
||||||
|
xa = np.zeros((NBVECS,2))
|
||||||
|
xa[:,0]=radius*np.cos(angle)
|
||||||
|
xa[:,1]=radius*np.sin(angle)
|
||||||
|
|
||||||
|
# All points are concatenated
|
||||||
|
X_train=np.concatenate((x,xa))
|
||||||
|
|
||||||
|
# First points (central cluster) are corresponding to class 0
|
||||||
|
# OTher points (annulus) are corresponding to class 1
|
||||||
|
Y_train=np.concatenate((np.zeros(NBVECS),np.ones(NBVECS)))
|
||||||
|
|
||||||
|
# Some bounds are computed for the graphical representation
|
||||||
|
x_min = X_train[:, 0].min()
|
||||||
|
x_max = X_train[:, 0].max()
|
||||||
|
y_min = X_train[:, 1].min()
|
||||||
|
y_max = X_train[:, 1].max()
|
||||||
|
|
||||||
|
# Training is done with a polynomial SVM
|
||||||
|
clf = svm.SVC(kernel='poly',gamma='auto', coef0=1.1)
|
||||||
|
clf.fit(X_train, Y_train)
|
||||||
|
|
||||||
|
# The classifier is tested with a first point inside first class
|
||||||
|
test1=np.array([0.4,0.1])
|
||||||
|
test1=test1.reshape(1,-1)
|
||||||
|
|
||||||
|
predicted1 = clf.predict(test1)
|
||||||
|
# Predicted class should be 0
|
||||||
|
print(predicted1)
|
||||||
|
|
||||||
|
# Second test is made with a point inside the second class (in the annulus)
|
||||||
|
test2=np.array([x_max,0]).reshape(1,-1)
|
||||||
|
|
||||||
|
predicted2 = clf.predict(test2)
|
||||||
|
# Predicted class should be 1
|
||||||
|
print(predicted2)
|
||||||
|
|
||||||
|
# The parameters of the trained classifier are printed to be used
|
||||||
|
# in CMSIS-DSP
|
||||||
|
supportShape = clf.support_vectors_.shape
|
||||||
|
|
||||||
|
nbSupportVectors=supportShape[0]
|
||||||
|
vectorDimensions=supportShape[1]
|
||||||
|
|
||||||
|
print("nbSupportVectors = %d" % nbSupportVectors)
|
||||||
|
print("vectorDimensions = %d" % vectorDimensions)
|
||||||
|
print("degree = %d" % clf.degree)
|
||||||
|
print("coef0 = %f" % clf.coef0)
|
||||||
|
print("gamma = %f" % clf._gamma)
|
||||||
|
|
||||||
|
print("intercept = %f" % clf.intercept_)
|
||||||
|
|
||||||
|
dualCoefs=clf.dual_coef_
|
||||||
|
dualCoefs=dualCoefs.reshape(nbSupportVectors)
|
||||||
|
supportVectors=clf.support_vectors_
|
||||||
|
supportVectors = supportVectors.reshape(nbSupportVectors*VECDIM)
|
||||||
|
|
||||||
|
print("Dual Coefs")
|
||||||
|
print(dualCoefs)
|
||||||
|
|
||||||
|
print("Support Vectors")
|
||||||
|
print(supportVectors)
|
||||||
|
|
||||||
|
# Graphical representation to display the cluster of points
|
||||||
|
# and the SVM boundary
|
||||||
|
r=plt.figure()
|
||||||
|
XX, YY = np.mgrid[x_min:x_max:200j, y_min:y_max:200j]
|
||||||
|
Z = clf.decision_function(np.c_[XX.ravel(), YY.ravel()])
|
||||||
|
|
||||||
|
# Put the result into a color plot
|
||||||
|
Z = Z.reshape(XX.shape)
|
||||||
|
|
||||||
|
levels = MaxNLocator(nbins=15).tick_values(Z.min(), Z.max())
|
||||||
|
|
||||||
|
cmap = plt.get_cmap('gray')
|
||||||
|
norm = BoundaryNorm(levels, ncolors=cmap.N, clip=True)
|
||||||
|
|
||||||
|
plt.pcolormesh(XX, YY, Z > 0, cmap=plt.get_cmap('gray'),norm=norm)
|
||||||
|
plt.contour(XX, YY, Z, colors=['k', 'k', 'k'],
|
||||||
|
linestyles=['--', '-', '--'], levels=[-.5, 0, .5])
|
||||||
|
|
||||||
|
scatter(x[:,0],x[:,1],s=1.0)
|
||||||
|
scatter(xa[:,0],xa[:,1],s=1.0)
|
||||||
|
|
||||||
|
# The test points are displayed in red.
|
||||||
|
scatter(test1[:,0],test1[:,1],s=6.0,color='Red')
|
||||||
|
scatter(test2[:,0],test2[:,1],s=6.0,color='Red')
|
||||||
|
show()
|
||||||
Loading…
Reference in New Issue