2795|0

433

帖子

4

TA的资源

纯净的硅(初级)

楼主
 

【Silicon Labs 开发套件评测】使用tensorflow原型开发手势识别项目 [复制链接]

  本帖最后由 北方 于 2021-9-10 16:41 编辑

1、首先需要引用一下资料来源

https://github.com/arduino/ArduinoTensorFlowLiteTutorials/

这个是arduino运用tensorflow的导则,后来看tensorflow也放弃了在lite上的工作,单独分出来tensorflow lite的子项目

https://github.com/tensorflow/tflite-micro

根据这两个资料可以进行掌握如何用这个工具开发

2、首先创建新的工程,感受gesture的智能工具。用原来的tensorflow范例为基准会更省事。

在新的包里安装六轴传感器,

这个是启动SPI接口读取数据的,后面的代码要根据这个API进行初始化,读取和解析。

可以登录网站获取,

https://docs.silabs.com/gecko-platform/3.2/hardware-driver/api/group-icm20648

 

3、tensorflow的原始数据

3.1 测试原始数据,根据arduino的数据读取如下图。那么这次读取的数据也要归一化到这样类似的数值范围,这样可以直接使用arduino范例库中的model。独自训练还是比较消耗时间的

Arduino Serial Plotter Output with Accelerometer Data

3.2 然后从arduino的下载包中,找到model.h。经过baking的model数据格式都是一样的,但是如果不用tensorflow的工具,是不能直接编辑和解析这个文件的。

具体的数据格式如下

需要改成model.h,或者直接复制过来。

3.3 对于数据处理是用下面类直接实现

加载model是用下面的语句,在setup()初始化中完成

HandleOutput()是自定义的事件处理句柄,可以直接在文件中查询。

3.4 按照上面的逻辑可以很快接用tensorflow的标准训练过程完成一个动态识别的移植,具体识别的手势可以参见上面的引用网址。不再解析。

4. 自定义和训练的方法流程

4.1 更多的情况下,大家还是希望自己训练程序和模型,那么还是建议基于上面的代码框架。

具体需要做的,首先是定义模型的输入数据数量和格式,然后是深度学习网络的结构,最后才是准备数据,开始训练。

4.2 准备数据

如上述采集六轴传感器的每次6组数据,读取数据如下

screenshot of serial monitor with IMU data

这组数据是把板子固定在手腕上,向左向右滑动,双击,旋转等任意自己希望定义的手势,至少重复10次,每次的数据都读出并保存在csv文件中,如

  • flex.csv.同时需要给每种手势一个数字编码。如1-10直接的自然数。

  • 4.2 进入训练阶段,这个需要熟悉tensorflow的流程,这个过程在需要科学学习的免费colab上的notebook文件https://colab.research.google.com/github/arduino/ArduinoTensorFlowLiteTutorials/blob/master/GestureToEmoji/arduino_tinyml_workshop.ipynb

为了便于学习全程粘贴如下,很长,但是值得读一下

不过其中最重要的模型一共15行代码,做成隐藏模式,只能直接使用。不能 编辑。这个就需要粉一下百度了,百度的paddlepaddle也做了一个类似的免费网络人工智能训练平台,很烧钱的,大家今早去免费薅羊毛。现在谷歌已经不能免费提供大家这样的服务了,百度估计也坚持不了多久,大家尽早去。

  • <a href="https://www.arduino.cc/"><img src="https://raw.githubusercontent.com/sandeepmistry/aimldevfest-workshop-2019/master/images/Arduino_logo_R_highquality.png" width=200/></a>
  • # Tiny ML on Arduino
  • ## Gesture recognition tutorial
  • * Sandeep Mistry - Arduino
  • * Don Coleman - Chariot Solutions
  • https://github.com/arduino/ArduinoTensorFlowLiteTutorials/
  • ## Setup Python Environment
  • The next cell sets up the dependencies in required for the notebook, run it.
  • # Setup environment
  • !apt-get -qq install xxd
  • !pip install pandas numpy matplotlib
  • !pip install tensorflow==2.0.0-rc1
  • # Upload Data
  • 1. Open the panel on the left side of Colab by clicking on the __>__
  • 1. Select the files tab
  • 1. Drag `punch.csv` and `flex.csv` files from your computer to the tab to upload them into colab.
  • # Graph Data (optional)
  • We'll graph the input files on two separate graphs, acceleration and gyroscope, as each data set has different units and scale.
  • import matplotlib.pyplot as plt
  • import numpy as np
  • import pandas as pd
  • filename = "punch.csv"
  • df = pd.read_csv("/content/" + filename)
  • index = range(1, len(df['aX']) + 1)
  • plt.rcParams["figure.figsize"] = (20,10)
  • plt.plot(index, df['aX'], 'g.', label='x', linestyle='solid', marker=',')
  • plt.plot(index, df['aY'], 'b.', label='y', linestyle='solid', marker=',')
  • plt.plot(index, df['aZ'], 'r.', label='z', linestyle='solid', marker=',')
  • plt.title("Acceleration")
  • plt.xlabel("Sample #")
  • plt.ylabel("Acceleration (G)")
  • plt.legend()
  • plt.show()
  • plt.plot(index, df['gX'], 'g.', label='x', linestyle='solid', marker=',')
  • plt.plot(index, df['gY'], 'b.', label='y', linestyle='solid', marker=',')
  • plt.plot(index, df['gZ'], 'r.', label='z', linestyle='solid', marker=',')
  • plt.title("Gyroscope")
  • plt.xlabel("Sample #")
  • plt.ylabel("Gyroscope (deg/sec)")
  • plt.legend()
  • plt.show()
  • # Train Neural Network
  • ## Parse and prepare the data
  • The next cell parses the csv files and transforms them to a format that will be used to train the fully connected neural network.
  • Update the `GESTURES` list with the gesture data you've collected in `.csv` format.
  • import matplotlib.pyplot as plt
  • import numpy as np
  • import pandas as pd
  • import tensorflow as tf
  • print(f"TensorFlow version = {tf.__version__}\n")
  • # Set a fixed random seed value, for reproducibility, this will allow us to get
  • # the same random numbers each time the notebook is run
  • SEED = 1337
  • np.random.seed(SEED)
  • tf.random.set_seed(SEED)
  • # the list of gestures that data is available for
  • GESTURES = [
  • "punch",
  • "flex",
  • ]
  • SAMPLES_PER_GESTURE = 119
  • NUM_GESTURES = len(GESTURES)
  • # create a one-hot encoded matrix that is used in the output
  • ONE_HOT_ENCODED_GESTURES = np.eye(NUM_GESTURES)
  • inputs = []
  • outputs = []
  • # read each csv file and push an input and output
  • for gesture_index in range(NUM_GESTURES):
  • gesture = GESTURES[gesture_index]
  • print(f"Processing index {gesture_index} for gesture '{gesture}'.")
  • output = ONE_HOT_ENCODED_GESTURES[gesture_index]
  • df = pd.read_csv("/content/" + gesture + ".csv")
  • # calculate the number of gesture recordings in the file
  • num_recordings = int(df.shape[0] / SAMPLES_PER_GESTURE)
  • print(f"\tThere are {num_recordings} recordings of the {gesture} gesture.")
  • for i in range(num_recordings):
  • tensor = []
  • for j in range(SAMPLES_PER_GESTURE):
  • index = i * SAMPLES_PER_GESTURE + j
  • # normalize the input data, between 0 to 1:
  • # - acceleration is between: -4 to +4
  • # - gyroscope is between: -2000 to +2000
  • tensor += [
  • (df['aX'][index] + 4) / 8,
  • (df['aY'][index] + 4) / 8,
  • (df['aZ'][index] + 4) / 8,
  • (df['gX'][index] + 2000) / 4000,
  • (df['gY'][index] + 2000) / 4000,
  • (df['gZ'][index] + 2000) / 4000
  • ]
  • inputs.append(tensor)
  • outputs.append(output)
  • # convert the list to numpy array
  • inputs = np.array(inputs)
  • outputs = np.array(outputs)
  • print("Data set parsing and preparation complete.")
  • ## Randomize and split the input and output pairs for training
  • Randomly split input and output pairs into sets of data: 60% for training, 20% for validation, and 20% for testing.
  • - the training set is used to train the model
  • - the validation set is used to measure how well the model is performing during training
  • - the testing set is used to test the model after training
  • # Randomize the order of the inputs, so they can be evenly distributed for training, testing, and validation
  • # https://stackoverflow.com/a/37710486/2020087
  • num_inputs = len(inputs)
  • randomize = np.arange(num_inputs)
  • np.random.shuffle(randomize)
  • # Swap the consecutive indexes (0, 1, 2, etc) with the randomized indexes
  • inputs = inputs[randomize]
  • outputs = outputs[randomize]
  • # Split the recordings (group of samples) into three sets: training, testing and validation
  • TRAIN_SPLIT = int(0.6 * num_inputs)
  • TEST_SPLIT = int(0.2 * num_inputs + TRAIN_SPLIT)
  • inputs_train, inputs_test, inputs_validate = np.split(inputs, [TRAIN_SPLIT, TEST_SPLIT])
  • outputs_train, outputs_test, outputs_validate = np.split(outputs, [TRAIN_SPLIT, TEST_SPLIT])
  • print("Data set randomization and splitting complete.")
  • ## Build & Train the Model
  • Build and train a [TensorFlow](https://www.tensorflow.org) model using the high-level [Keras](https://www.tensorflow.org/guide/keras) API.
  • # build the model and train it
  • model = tf.keras.Sequential()
  • model.add(tf.keras.layers.Dense(50, activation='relu')) # relu is used for performance
  • model.add(tf.keras.layers.Dense(15, activation='relu'))
  • model.add(tf.keras.layers.Dense(NUM_GESTURES, activation='softmax')) # softmax is used, because we only expect one gesture to occur per input
  • model.compile(optimizer='rmsprop', loss='mse', metrics=['mae'])
  • history = model.fit(inputs_train, outputs_train, epochs=600, batch_size=1, validation_data=(inputs_validate, outputs_validate))
  • ## Verify
  • Graph the models performance vs validation.
  • ### Graph the loss
  • Graph the loss to see when the model stops improving.
  • # increase the size of the graphs. The default size is (6,4).
  • plt.rcParams["figure.figsize"] = (20,10)
  • # graph the loss, the model above is configure to use "mean squared error" as the loss function
  • loss = history.history['loss']
  • val_loss = history.history['val_loss']
  • epochs = range(1, len(loss) + 1)
  • plt.plot(epochs, loss, 'g.', label='Training loss')
  • plt.plot(epochs, val_loss, 'b', label='Validation loss')
  • plt.title('Training and validation loss')
  • plt.xlabel('Epochs')
  • plt.ylabel('Loss')
  • plt.legend()
  • plt.show()
  • print(plt.rcParams["figure.figsize"])
  • ### Graph the loss again, skipping a bit of the start
  • We'll graph the same data as the previous code cell, but start at index 100 so we can further zoom in once the model starts to converge.
  • # graph the loss again skipping a bit of the start
  • SKIP = 100
  • plt.plot(epochs[SKIP:], loss[SKIP:], 'g.', label='Training loss')
  • plt.plot(epochs[SKIP:], val_loss[SKIP:], 'b.', label='Validation loss')
  • plt.title('Training and validation loss')
  • plt.xlabel('Epochs')
  • plt.ylabel('Loss')
  • plt.legend()
  • plt.show()
  • ### Graph the mean absolute error
  • [Mean absolute error](https://en.wikipedia.org/wiki/Mean_absolute_error) is another metric to judge the performance of the model.
  • # graph of mean absolute error
  • mae = history.history['mae']
  • val_mae = history.history['val_mae']
  • plt.plot(epochs[SKIP:], mae[SKIP:], 'g.', label='Training MAE')
  • plt.plot(epochs[SKIP:], val_mae[SKIP:], 'b.', label='Validation MAE')
  • plt.title('Training and validation mean absolute error')
  • plt.xlabel('Epochs')
  • plt.ylabel('MAE')
  • plt.legend()
  • plt.show()
  • ### Run with Test Data
  • Put our test data into the model and plot the predictions
  • # use the model to predict the test inputs
  • predictions = model.predict(inputs_test)
  • # print the predictions and the expected ouputs
  • print("predictions =\n", np.round(predictions, decimals=3))
  • print("actual =\n", outputs_test)
  • # Plot the predictions along with to the test data
  • plt.clf()
  • plt.title('Training data predicted vs actual values')
  • plt.plot(inputs_test, outputs_test, 'b.', label='Actual')
  • plt.plot(inputs_test, predictions, 'r.', label='Predicted')
  • plt.show()
  • # Convert the Trained Model to Tensor Flow Lite
  • The next cell converts the model to TFlite format. The size in bytes of the model is also printed out.
  • # Convert the model to the TensorFlow Lite format without quantization
  • converter = tf.lite.TFLiteConverter.from_keras_model(model)
  • tflite_model = converter.convert()
  • # Save the model to disk
  • open("gesture_model.tflite", "wb").write(tflite_model)
  • import os
  • basic_model_size = os.path.getsize("gesture_model.tflite")
  • print("Model is %d bytes" % basic_model_size)
  • ## Encode the Model in an Arduino Header File
  • The next cell creates a constant byte array that contains the TFlite model. Import it as a tab with the sketch below.
  • !echo "const unsigned char model[] = {" > /content/model.h
  • !cat gesture_model.tflite | xxd -i >> /content/model.h
  • !echo "};" >> /content/model.h
  • import os
  • model_h_size = os.path.getsize("model.h")
  • print(f"Header file, model.h, is {model_h_size:,} bytes.")
  • print("\nOpen the side panel (refresh if needed). Double click model.h to download the file.")
  • # Classifying IMU Data
  • Now it's time to switch back to the tutorial instructions and run our new model on the Arduino Nano 33 BLE Sense to classify the accelerometer and gyroscope data.

  • 4.3 训练后的就生产了model.h文件,这样就可以如上一节一样来用自定义的模型实现自定义的手势。上面的代码就是一个用手势替代emojo键盘的方式。

  • 需要注意的是,这个识别的准确率并不高,有识别错误的概率。一个是训练的数据不够多,另一个是经过压缩的模型有损失了很多的精度。不过用于非严格的方案,还是一个神奇的方法。

  • 在arduino的范例里,还有一个简单的语音识别模型。这个模型,识别的是up,down等英语上下单词,可以用来控制小车。不过,普遍反映,这个模型的识别效果不那么好。

 

 

 

点赞 关注
 
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条
有奖直播 | AI之眼——安森美图像传感器 报名中
直播时间:2025年4月25日(周五)上午10:00-11:30
直播主题:AI之眼——安森美图像传感器
报名观看直播、直播间提问、填写问卷均有机会获得精美礼品!

查看 »

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网 1

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表