根据个人经验总结的深度学习入门路线(简单快速)
https://blog.csdn.net/weixin_44414948/article/details/109704871
深度学习入门二阶段demo练习:
https://blog.csdn.net/weixin_44414948/article/details/110673660
任务要求
使用深度学习框架(tensorflow2.0及以上、pytorch1.0及以上版本)搭建卷积神经网络。
数据集:骨架行为数据集,准确率高于60%。
追加要求:同一图表绘制训练过程的loss、acc曲线,截取测试集准确率的图。
骨架行为数据集简介
该数据集是由本课题组行为检测方向同学自行采集,共有奔跑、跳跃、倚靠产品、吸烟、玩手机、背景行为共6种行为种类标签,数据为人体骨架节点(25点)序列的txt文件,共60万帧,示例如下图所示,每行共有75个点(25个关节点的xyz坐标),一行为一帧。
完整实现代码
import tensorflow as tf
from tensorflow.keras import layers, optimizers, datasets, Sequential, metrics
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
conv_layers = [
# 卷积层 + 池化层
layers.Conv2D(64, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),
layers.Conv2D(64, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),
layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'),
layers.Conv2D(128, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),
layers.Conv2D(128, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),
layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'),
layers.Conv2D(256, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),
layers.Conv2D(256, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),
layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'),
layers.Conv2D(512, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),
layers.Conv2D(512, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),
layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'),
layers.Conv2D(512, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),
layers.Conv2D(512, kernel_size=[3, 3], padding='same', activation=tf.nn.relu),
layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'),
]
def preprocess(x, y):
x = tf.cast(x, dtype=tf.float32) / 255.
y = tf.cast(y, dtype=tf.int32)
return x, y
#导入数据集
X = []
Y = []
data = pd.read_table('E:\\PycharmProjects\\untitled\\1-action_seq.txt', sep=',', header=None)
data = data.iloc[:, :75]
label = pd.read_table('E:\\PycharmProjects\\untitled\\1-label_class.txt', header= None)
for i in range(data.shape[0]):
X.append(list(data.iloc[i, :].values))
for j in range(label.shape[0]):
Y.append(list(label.iloc[j, :].values)) #对应的二维numpy值数组
Z = []
for i in range(len(X)):
Z.append(X[i] + Y[i])
A = []
B = []
np.random.shuffle(Z)
for i in range(len(Z)):
A.append(Z[i][:75])
B.append(Z[i][-1])
x = A[:int(len(A) * 0.8)]
x = tf.reshape(x, [int(len(A) * 0.8), 25, 3, 1])
x_test = A[int(len(A) * 0.8):]
x_test = tf.reshape(x_test, [int(len(A) * 0.2)+1, 25, 3, 1])
y = B[:int(len(A) * 0.8)]
y_test = B[int(len(A) * 0.8):]
# y = tf.squeeze(y, axis=1)
# y_test = tf.squeeze(y_test, axis=1)
# print(x.shape, y.shape, x_test.shape, y_test.shape)
train_db = tf.data.Dataset.from_tensor_slices((x, y))
train_db = train_db.shuffle(1000).map(preprocess).batch(100)
test_db = tf.data.Dataset.from_tensor_slices((x_test, y_test))
test_db = test_db.map(preprocess).batch(100)
sample = next(iter(train_db))
print('sample:', sample[0].shape, sample[1].shape, tf.reduce_min(sample[0]), tf.reduce_max(sample[0]))
def main():
#[b, 25, 3, 1] => [b, 1, 1, 512]
conv_net = Sequential(conv_layers)
#全连接层
fc_net = Sequential([
layers.Dense(256, activation=tf.nn.relu),
layers.Dense(128, activation=tf.nn.relu),
layers.Dense(64, activation=tf.nn.relu),
layers.Dense(6, activation=tf.nn.relu),
])
conv_net.build(input_shape=[None, 25, 3, 1])
fc_net.build(input_shape=[None, 512])
#优化器
optimizer = optimizers.Adam(lr = 0.001)
variables = conv_net.trainable_variables + fc_net.trainable_variables
for epoch in range(2):
for step, (x, y) in enumerate(train_db):
# 求梯度
with tf.GradientTape() as tape:
# [b, 25, 3, 1] => [b, 1, 1, 512]
out = conv_net(x)
# squeeze 也可以叫做 reshape
# flatten 输出成平坦的变量 => [b, 512]
out = tf.reshape(out, [-1, 512])
#全连接层的输出,也叫做 logits, [b, 512] => [b, 6]
logits = fc_net(out)
#loss的计算
#先把y转化为onthot格式,[b] => [b, 6]
y_onehot = tf.one_hot(y, depth=6) #因为是6分类
loss = tf.losses.categorical_crossentropy(y_onehot, logits, from_logits=True)
#计算均值
loss = tf.reduce_mean(loss)
#计算梯度
grads = tape.gradient(loss, variables) #对所有参数进行求导, y轴为loss, x轴为 variables.
#梯度的更新(需要设计优化器)
optimizer.apply_gradients(zip(grads, variables))
#打印一下
if step % 100 == 0:
print(epoch, step, 'loss:', float(loss))
#做测试
total_num = 0
total_correct = 0
for x, y in test_db:
out = conv_net(x)
out = tf.reshape(out, [-1, 512])
logits = fc_net(out)
prob = tf.nn.softmax(logits, axis=1)#第一根轴
#预测最大值的位置
pred = tf.argmax(prob, axis=1)
pred = tf.cast(pred, dtype=tf.int32)
#真实的值
correct = tf.cast(tf.equal(pred, y), dtype=tf.int32)
correct = tf.reduce_sum(correct)
total_num += x.shape[0]
total_correct += int(correct)
acc = total_correct / total_num
print(epoch, 'acc:', acc)
# 输入两个曲线的信息
plt.figure(figsize=(12, 8), dpi=80)
plt.plot(epoch, acc, color='g', linestyle='-.', label='acc')
plt.plot(epoch, loss, color='r', linestyle='--', label='loss')
# 显示图例
plt.legend() # 默认loc=Best
# 添加网格信息
plt.grid(True, linestyle='--', alpha=0.5) # 默认是True,风格设置为虚线,alpha为透明度
# 添加标题
plt.xlabel('epochs')
plt.ylabel('loss/acc')
plt.title('inception_Curve of loss/acc Change with epochs in GJData')
plt.savefig('E:\\PycharmProjects\\untitled\\inception.jpg')
plt.show()
if __name__ == '__main__':
main()
训练过程曲线图
注:师弟做得还是挺不错的,点个赞