基于手机传感器数据使用 CNN 识别用户行为的 PyTorch 实现

原文章是使用tensorflow实现的,这里重新使用了PyTorch实现一下。

model.py

import torch
import torch.nn as nn
import numpy as np
class SmartphoneActivityRecognitionCNN(nn.Module):
    def __init__(self,  dropout_rate=0.3):
        super(SmartphoneActivityRecognitionCNN, self).__init__()

        # 卷积层部分

        self.model =nn.Sequential(
                nn.Conv1d(3, 96, kernel_size=(10,)),
                nn.ReLU(),
                nn.MaxPool1d(kernel_size=3,stride=3),

                nn.Conv1d(96, 192, kernel_size=(10,)),
                nn.ReLU(),
                nn.MaxPool1d(kernel_size=3,stride=3)
            )

        # 全连接层部分
        self.flatten = nn.Flatten()
        self.dropout = nn.Dropout(dropout_rate)
        self.fc = nn.Linear(1920, 6)

        self.softmax = nn.Softmax(dim=1)
    def forward(self, x):
        x = self.model(x)
        x = self.flatten(x)
        x = self.dropout(x)
        x = self.fc(x)
        x = self.softmax(x)
        return x

data.py

import torch
from torch.utils.data import Dataset
import numpy as np
import pandas as pd
from pandas import DataFrame


def feature_normalize(dataset):
    mu = np.mean(dataset, axis=0)
    sigma = np.std(dataset, axis=0)
    return (dataset - mu) / sigma
class CNNDataset(Dataset):
    def __init__(self,train = False,transfrom = None,file_path = "./datas/WISDM_ar_v1.1_fix.txt"):
        super(CNNDataset, self).__init__()
        column_names = ['user-id', 'activity', 'timestamp', 'x-axis', 'y-axis', 'z-axis']
        self.data = pd.read_csv(file_path,header=None,names=column_names,on_bad_lines='skip')
        self.data.dropna(axis=0,inplace=True)
        self.data['x-axis'] = feature_normalize(self.data['x-axis'])
        self.data['y-axis'] = feature_normalize(self.data['y-axis'])
        self.data['z-axis'] = feature_normalize(self.data['z-axis'])
        self.class_dict = {
            "Walking":0,
            "Jogging":1,
            "Upstairs":2,
            "Downstairs":3,
            "Sitting":4,
            "Standing":5
        }
        self.train = train
        self.transfrom = transfrom
    def __len__(self):
        if self.train:
            return int(((self.data.shape[0] - 64) * 0.7) / 64)
        else:
            return int(((self.data.shape[0]- 64) * 0.3)  / 64)

    def __getitem__(self,index):
        bias = 0
        if self.train == False:
            bias = int((self.data.shape[0]- 64) * 0.7) + 1
        x = self.data['x-axis'][bias + index * 64 : bias + index * 64 + 128]
        y = self.data['y-axis'][bias + index * 64 : bias + index * 64 + 128]
        z = self.data['z-axis'][bias + index * 64: bias + index * 64 + 128]
        labels = self.data['activity'][bias + index * 64 : bias + index * 64 + 128].value_counts().idxmax()
        # 创建3通道的numpy数组
        datas = np.stack((x, y, z))
        return torch.tensor(datas,dtype=torch.float32) , self.class_dict[labels]

trian.py

import torchvision.transforms
from torch import nn

from model import  SmartphoneActivityRecognitionCNN
from torch.utils.data import DataLoader
from data import CNNDataset
import torch
from torch.utils.tensorboard import SummaryWriter

writer = SummaryWriter('./log')

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

if __name__ == '__main__':
    data_train = CNNDataset(train=True)
    data_test = CNNDataset(train=False)

    dataloader_train = DataLoader(data_train, batch_size=128, num_workers=3)
    dataloader_test = DataLoader(data_test, batch_size=128, num_workers=3)

    # 模型定义
    model = SmartphoneActivityRecognitionCNN()
    model = model.to(device)

    loss_fn = nn.CrossEntropyLoss()
    loss_fn = loss_fn.to(device)

    optimizer = torch.optim.SGD(model.parameters(), lr=0.001, weight_decay=0.00005, momentum=0.5)

    epochs = 5000
    train_counter = 0

    for epoch in range(epochs):
        print("Epoch {}/{}".format(epoch + 1, epochs))
        model.train()
        for datas, labels in dataloader_train:
            datas = datas.to(device)
            labels = labels.to(device)
            optimizer.zero_grad()
            outputs = model(datas)
            loss = loss_fn(outputs, labels)
            loss.backward()
            optimizer.step()
            train_counter += 1
            writer.add_scalar('loss', loss.item(), train_counter)
            if train_counter % 100 == 0:
                print("总的训练次数: {},loss:{}".format(train_counter, loss.item()))
        total_test_loss = 0.0
        total_test_acc = 0.0
        model.eval()
        with torch.no_grad():
            for datas, labels in dataloader_test:
                datas = datas.to(device)
                labels = labels.to(device)
                outputs = model(datas)
                test_loss = loss_fn(outputs, labels)
                total_test_loss = total_test_loss + test_loss.item()
                accuracy = (outputs.argmax(1)==labels).sum()
                total_test_acc = total_test_acc + accuracy
        print("整体测试集上的总loss: {}, acc: {}".format(total_test_loss, total_test_acc / len(data_test)))
        writer.add_scalar('accuracy', total_test_acc / len(data_test) * 100, train_counter)
        if epoch % 10 == 0:
            torch.save(model.state_dict(), "./weights/model{}.pth".format(epoch))
    writer.close()

但是有个问题就是总是跑不到原文章的88%的准确度,不知道是哪里出现了问题有懂得大佬评论一下!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值