1.安装
sudo python -m pip install turicreate
2.activity classifier
- 数据预处理,生成turicreate识别的sFrame格式
from glob import glob
import turicreate as tc
# load labels
labels = tc.SFrame.read_csv('./HAPT Data Set/RawData/labels.txt',
delimiter=' ',
header=False,
verbose=False)
labels = labels.rename({
'X1': 'exp_id',
'X2': 'user_id',
'X3': 'activity_id',
'X4': 'start',
'X5': 'end'
})
def find_label_for_containing_interval(intervals, index):
containing_interval = intervals[:, 0][(intervals[:, 1] <= index) & (index <= intervals[:, 2])]
if len(containing_interval) == 1:
return containing_interval[0]
# load data
data = tc.SFrame()
acc_files = glob('./HAPT Data Set/RawData/acc_*.txt')
gyro_files = glob('./HAPT Data Set/RawData/gyro_*.txt')
files = zip(sorted(acc_files), sorted(gyro_files))
for acc_file, gyro_file in files:
exp_id = int(acc_file.split('_')[1][-2:])
user_id = int(acc_file.split('_')[2][4:6])
# load accel data
sf = tc.SFrame.read_csv(acc_file,
delimiter=' ',
header=False,
verbose=False)
sf = sf.rename({
'X1': 'acc_x',
'X2': 'acc_y',
'X3': 'acc_z'
})
sf['exp_id'] = exp_id
sf['user_id'] = user_id
# load gyro data
gyro_sf = tc.SFrame.read_csv(gyro_file,
delimiter=' ',
header=False,
verbose=False)
gyro_sf = gyro_sf.rename({
'X1': 'gyro_x',
'X2': 'gyro_y',
'X3': 'gyro_z'
})
sf = sf.add_columns(gyro_sf)
# calc labels
exp_labels = labels[labels['exp_id'] == exp_id][['activity_id', 'start', 'end']].to_numpy()
sf = sf.add_row_number()
sf['activity_id'] = sf['id'].apply(
lambda x: find_label_for_containing_interval(exp_labels, x)
)
sf = sf.remove_columns(['id', 'exp_id'])
data = data.append(sf)
target_map = {
1.: 'walking',
2.: 'climbing_upstairs',
3.: 'climbing_downstairs',
4.: 'sitting',
5.: 'standing',
6.: 'laying'
}
# use the same labels used in the experiment
data = data.filter_by(target_map.keys(), 'activity_id')
data['activity'] = data['activity_id'].apply(
lambda x: target_map[x]
)
data = data.remove_column('activity_id')
data.save('hapt_data.sframe')
生成的sframe文件:
sframe文件具体每个文件是什么意思,还没搞懂...
根据生成的sframe训练core ml所需的mlmodel文件
import turicreate as tc
# load sessions from preprocessed data
data = tc.SFrame('hapt_data.sframe')
# train/test split by recording sessions
train, test = tc.activity_classifier.util.random_split_by_session(
data,
session_id='user_id',
fraction=0.8
)
# create an activity classifier
model = tc.activity_classifier.create(
train,
session_id='user_id',
target='activity',
prediction_window=50
)
# evaluate the model and save the results into a dictionary
metrics = model.evaluate(test)
print metrics['accuracy']
# save the model for later use in turi create
model.save('mymodel.model')
# export for use in core ml
model.export_coreml('MyActivityClassifier.mlmodel')
train result
训练的准确率一般啦!!!
model的高级运用:
walking_3_sec = data[(data['activity'] == 'walking') & (data['user_id'] == 1)][50:200]
print model.predict(walking_3_sec, output_frequency='per_window')
print model.predict(walking_3_sec, output_frequency='per_row')
3.把model放到app中使用
建个工程,把mlmodel拉进去
project然后按照文档说明把预测代码写到ViewController.swift里
import UIKit
import CoreML
import CoreMotion
class ViewController: UIViewController {
let motionManager = CMMotionManager()
struct ModelConstants {
static let numOfFeatures = 6
static let predictionWindowSize = 50
static let sensorsUpdateInterval = 1.0 / 50.0
static let hiddenInLength = 200
static let hiddenCellInLength = 200
}
let activityClassificationModel = MyActivityClassifier()
var currentIndexInPredictionWindow = 0
let predictionWindowDataArray = try? MLMultiArray(
shape: [1 , ModelConstants.predictionWindowSize , ModelConstants.numOfFeatures] as [NSNumber],
dataType: MLMultiArrayDataType.double
)
var lastHiddenOutput = try? MLMultiArray(
shape: [ModelConstants.hiddenInLength as NSNumber],
dataType: MLMultiArrayDataType.double
)
var lastHiddenCellOutput = try? MLMultiArray(
shape: [ModelConstants.hiddenCellInLength as NSNumber],
dataType: MLMultiArrayDataType.double
)
override func viewDidLoad() {
super.viewDidLoad()
motionManager.accelerometerUpdateInterval = TimeInterval(ModelConstants.sensorsUpdateInterval)
motionManager.gyroUpdateInterval = TimeInterval(ModelConstants.sensorsUpdateInterval);
motionManager.startAccelerometerUpdates(to: .main) { accelerometerData, error in
guard let accelerometerData = accelerometerData else { return }
self.addAccelSampleToDataArray(accelSample: accelerometerData)
}
}
func addAccelSampleToDataArray(accelSample: CMAccelerometerData) {
// add the current accelermeter reading to the data array
guard let dataArray = predictionWindowDataArray else {
return
}
dataArray[[0, currentIndexInPredictionWindow, 0] as [NSNumber]] = accelSample.acceleration.x as NSNumber
dataArray[[0, currentIndexInPredictionWindow, 1] as [NSNumber]] = accelSample.acceleration.y as NSNumber
dataArray[[0, currentIndexInPredictionWindow, 2] as [NSNumber]] = accelSample.acceleration.z as NSNumber
// update the index in the prediction window data array
currentIndexInPredictionWindow += 1
// if the data array if full, call the prediction method to get a new model prediction.
// we assume here for simplicity that the gyro data was added to the data array as well.
if (currentIndexInPredictionWindow == ModelConstants.predictionWindowSize) {
let predictedActivity = performModelPrediction() ?? "N/A"
// use the predicted activity here
print(predictedActivity)
// start a new prediction window
currentIndexInPredictionWindow = 0
}
}
func performModelPrediction() -> String? {
guard let dataArray = predictionWindowDataArray else {
return "error"
}
// perform model prediction
let modelPrediction = try? activityClassificationModel.prediction(
features: dataArray,
hiddenIn: lastHiddenOutput,
cellIn: lastHiddenCellOutput
)
// update the state vectors
lastHiddenOutput = modelPrediction?.hiddenOut
lastHiddenCellOutput = modelPrediction?.cellOut
// return the predicted activity - the activity with the highest probability
return modelPrediction?.activity
}
}
代码这么简单,就不另外放demo地址了,把代码贴上去就可以直接跑了.
于是就可以打印出预测的接下来动作了
result还是很准的!
网友评论