2025.2.11
在进行了一段时间内的试错后,重新整理思路:
由于
1.每个数据集数据量比较大,自己提取特征麻烦且不好掌握,故思考使用深度学习模型直接训练原时间序列。
2.由于数据标签只有312个,比较小,不适用于深度学习,故考虑进行数据增强。
3.经研究,可将数据用滑动窗口切片,把每个标签对应的数据切成十份,这样就可以有3120个标签,极大的增加了数据量。最好确保每个切片的长度相同,这样能够给深度学习模型提供一致的输入格式。
4.滑动窗口切片:可以使用滑动窗口方法,设置固定的步长(比如10秒或20秒),从每个时间序列中提取重叠的切片。这样既可以从每个文件中提取多个切片,又能避免丢失重要的时序信息。
1.数据集制作:
思路:我现在要制作数据集,但是我觉得思路好混乱,我要从文件名中提取出特征,要从txt文件中利用滑动窗口将数据切片,然后把这文件名中的特征和数据切片合并,然后再给合并后的数据添上标签。该步骤我要给所有txt文件都处理一边,再把所有处理后的数据及标签堆在一起,作为训练数据集。请帮我梳理一下思路。
你的思路基本上是正确的,我来帮你梳理一下流程。以下是针对你任务的简化步骤,你可以按照这些步骤逐步完成数据集的构建。
总体流程:
- 从文件名中提取特征(数据来源、步态编号等)。
- 加载每个
.txt
文件的传感器数据。 - 使用滑动窗口将时间序列数据切片。
- 合并文件名特征与切片数据。
- 为每个数据片段添加标签(例如是否为PD患者)。
- 将所有处理后的数据合并成一个训练数据集。
具体步骤:
1. 提取文件名特征
每个文件名遵循固定格式,如 GaCo01_02.txt
,我们可以从中提取出数据来源(Ga
、Ju
、Si
)和步态编号(01
、10
)等特征。根据你的需求,这些特征可以作为模型的输入(如果需要),或者作为额外的标签信息。
2. 加载 .txt
文件中的数据
每个 .txt
文件包含一系列传感器的数据。你需要读取这些文件并按每秒的传感器数据存储。数据的结构通常是每秒的数据(例如18个传感器的读数)。
3. 使用滑动窗口切片数据
对于每个文件中的时间序列数据,你可以使用滑动窗口技术。假设每个滑动窗口代表一个样本,你需要确定窗口大小和步长(例如,窗口大小50秒,步长10秒)。这意味着你会在每个文件中生成多个切片,每个切片都是一个新的数据点。
4. 合并文件名特征与数据切片
每次切片时,从文件名中提取出的特征会与相应的时间窗口数据一起保存。例如,如果数据来源是 Ga
,步态编号是 01
,那么每个切片数据就会带上这些信息。
5. 添加标签
假设你用文件名中的 Co
和 Pt
作为标签,Co
代表对照组(标签0),Pt
代表PD患者(标签1)。这些标签会随着每个数据切片一起保存。
6. 合并所有数据
最后,你会将所有文件的切片数据、特征和标签合并成一个大的训练数据集。这个数据集将包含多个样本,每个样本都有对应的特征和标签。
import os
import re
import numpy as np
# 提取文件名特征的函数
def extract_features(file_name):
match = re.match(r"([A-Za-z]{2})([A-Za-z]{2})(\d{2})_(\d{2})\.txt", file_name)
if match:
data_source = match.group(1) # 数据来源 (Ga, Ju, Si)
gait_type = match.group(4) # 步态编号 (如 01, 10)
# 转换数据来源为完整名称
data_source_mapping = {
"Ga": 0, # 0代表Galit Yogev
"Ju": 1, # 1代表Hausdorff
"Si": 2 # 2代表Silvi Frenkel-Toledo
}
# 转换步态编号为描述
gait_type_mapping = {
"01": 0, # 0代表正常行走
"02": 1, # 1代表双任务行走
"03": 2, # 0代表正常行走
"04": 3, # 1代表双任务行走
"05": 4, # 0代表正常行走
"06": 5, # 1代表双任务行走
"07": 6, # 0代表正常行走
"08": 7, # 1代表双任务行走
"09": 8, # 0代表正常行走
"10": 9 # 1代表双任务行走
}
data_source_code = data_source_mapping.get(data_source, -1) # 默认为-1表示未知
gait_type_code = gait_type_mapping.get(gait_type, -1) # 默认为-1表示未知
return data_source_code, gait_type_code
else:
return None, None
# 使用滑动窗口切片时间序列数据的函数
def sliding_window_slice(data, window_size, step_size):
slices = []
for start in range(0, len(data) - window_size + 1, step_size):
end = start + window_size
slice_data = data[start:end]
slices.append(slice_data)
#print(f"{file_name} 的切片数量: {len(slices)}")#打印一下每个文件的切片数量,确保它符合预期,有可能卡慎用
return slices
def add_features_as_columns(slice_data, data_source, gait_type):
"""
将 data_source 和 gait_type 作为两列数据添加到 slice_data 后面。
Args:
slice_data (numpy.ndarray): 形状为 (600, 19) 的数据。
data_source (int): 数据来源特征。
gait_type (int): 步态类型特征。
Returns:
numpy.ndarray: 添加特征后的数据,形状为 (600, 21)。
"""
# 1. 将 data_source 和 gait_type 扩展为列向量
data_source_column = np.full((slice_data.shape[0], 1), data_source) # 形状为 (600, 1)
gait_type_column = np.full((slice_data.shape[0], 1), gait_type) # 形状为 (600, 1)
# 2. 将扩展后的列向量拼接到 slice_data 后面
new_data = np.concatenate((slice_data, data_source_column, gait_type_column), axis=1)
return new_data
# 处理文件夹中的所有txt文件,生成数据集
def process_files_in_folder(folder_path, window_size=600, step_size=100):
data = []
labels = []
# 获取文件夹中的所有txt文件
files = os.listdir(folder_path)
txt_files = [file for file in files if file.endswith('.txt')]
for file_name in txt_files:
# 提取文件名特征(数据来源、步态类型)
data_source, gait_type = extract_features(file_name)
#print(f"文件名: {file_name} , 数据来源: {data_source}, 步态类型: {gait_type}")#检查文件名特征提取是否正确
if data_source is not None and gait_type is not None:
# 加载传感器数据(假设数据是以空格或逗号分隔的数字)
file_path = os.path.join(folder_path, file_name)
sensor_data = np.loadtxt(file_path) # 根据实际格式调整加载方式
# 使用滑动窗口切片
slices = sliding_window_slice(sensor_data, window_size, step_size)
# 给每个切片添加标签(例如根据文件名中的组别信息)
label = 0 if 'Co' in file_name else 1 # Co -> 0, Pt -> 1
#print(f"文件名: {file_name}, 标签: {label}")#验证标签是否正确
# 将数据来源和步态类型特征附加到每个切片
for slice_data in slices:
# 将数据来源和步态类型特征附加到传感器数据
#feature_data = np.append(slice_data, [data_source, gait_type]) # 拼接特征到数据切片
feature_data=add_features_as_columns(slice_data, data_source, gait_type)
data.append(feature_data)
labels.append(label)
#print(f"文件名: {file_name}, 标签: {label}")
else:
print(f"文件名 {file_name} 格式不正确,跳过")
# 将所有数据堆叠成训练集
data = np.array(data)
labels = np.array(labels)
print(f"切片数据集形状:{data[100].shape}")
print(f"堆叠后数据集形状:{data.shape}")
print(data[1000][:, -2:])
print(f"{data_source}")
print(f"{gait_type}")
print(f"加入特征后数据形状: {feature_data.shape}")
print(f"传感器数据形状: {slice_data.shape}")
return data, labels
# 设置文件夹路径
folder_path = 'E:/gxy/gxy/D/teach/footbed/gait-in-parkinsons-disease-1.0.0/gait-in-parkinsons-disease-1.0.0' # 请替换为实际路径
# 处理文件并生成训练数据集
X, y = process_files_in_folder(folder_path)
print(f"训练数据集形状: {X.shape}")
print(f"标签形状: {y.shape}")
#print(f"文件名: {file_name}, 标签: {label}")
要验证数据集生成的是否正确,可以从以下几个方面进行检查:
1. 文件名特征提取是否正确
- 检查正则表达式是否正确提取了文件名特征:
- 你可以打印一些提取出来的特征,确保每个文件的
数据来源
和步态编号
都能正确地从文件名中提取出来。- 例如:
python
复制编辑
data_source, gait_type = extract_features(file_name) print(f"文件名: {file_name}, 数据来源: {data_source}, 步态类型: {gait_type}")
2. 检查数据切片
- 检查滑动窗口切片的数量和大小:
- 确保滑动窗口的大小
window_size
和步长step_size
适当。- 确保切片的数量符合预期,即每个文件应该有多个切片。例如,如果原始数据有 12000 个时间点,滑动窗口的大小为 50,步长为 10,那么每个文件应该产生
(12000 - 50) / 10 + 1 = 1196
个切片。- 打印一下每个文件的切片数量,确保它符合预期:
python
复制编辑
print(f"{file_name} 的切片数量: {len(slices)}")
3. 标签是否正确
- 检查标签的正确性:
- 标签是根据文件名中的
Co
和Pt
来决定的。你可以打印标签来确保它们符合预期。- 例如:
python
复制编辑
print(f"文件名: {file_name}, 标签: {label}")
4. 检查数据合并
- 检查数据与特征是否正确合并:
- 每个数据切片应该是原始传感器数据与文件名中的特征(如数据来源和步态编号)的组合。检查
feature_data
是否确实包含了传感器数据和附加的特征。- 例如:
python
复制编辑
print(f"第一个数据切片: {data[0]}")
5. 检查数据集维度
- 检查最终数据集的形状:
- 确保
X
和y
的形状符合预期。比如,如果每个切片有 50 个时间步,每个时间步有 18 个传感器数据,再加上 2 个附加特征,那么每个样本的维度应该是50 * 18 + 2
。- 你可以检查数据的形状来确保它符合预期:
python
复制编辑
print(f"训练数据集形状: {X.shape}") print(f"标签形状: {y.shape}")
6. 数据可视化
- 可视化检查数据是否合理:
- 你可以通过可视化来进一步验证数据的合理性。例如,可以绘制一些切片的传感器数据,检查是否符合预期的趋势。
- 例如:
python
复制编辑
import matplotlib.pyplot as plt plt.plot(X[0, :50]) # 可视化第一个切片的前50个时间步的数据 plt.show()
7. 样本标签的分布
- 检查标签的分布:
- 确保标签分布合理(即标签为
0
和1
的数量大致平衡,或至少符合实际数据集的比例)。你可以打印一下标签的分布:python
复制编辑
print(f"标签分布: {np.bincount(y)}")
8. 处理文件夹路径问题
- 确保文件路径正确:
- 确保代码能够正确加载指定文件夹中的
.txt
文件。如果路径错误或文件名格式不符合预期,可能会导致数据加载失败。- 可以先打印文件路径,确保路径指向正确的文件夹:
python
复制编辑
print(f"文件路径: {file_path}")
9. 异常处理
- 处理异常情况:
- 在代码中加入更多的异常处理来捕获潜在的错误,例如文件读取失败、数据格式不正确等情况。
- 例如,在加载数据时,如果遇到无法读取的文件,可以使用
try-except
块来捕获错误:python
复制编辑
try: sensor_data = np.loadtxt(file_path) except Exception as e: print(f"无法读取文件 {file_name}: {e}") continue
10. 检查生成数据是否符合任务目标
- 对照任务目标进行检查:
- 根据你的任务目标,确认生成的数据是否合理。例如,如果你训练一个分类模型,确保输入数据的形状和标签与模型的输入要求一致。
通过以上步骤,你可以逐步验证数据集的生成是否存在问题。如果发现问题,可以进一步定位并修复。
运行结果:
文件名 demographics.txt 格式不正确,跳过 文件名 format.txt 格式不正确,跳过 文件名 SHA256SUMS.txt 格式不正确,跳过 切片数据集形状:(600, 21) 堆叠后数据集形状:(31549, 600, 21) [[0. 1.] [0. 1.] [0. 1.] ... [0. 1.] [0. 1.] [0. 1.]] 2 0 加入特征后数据形状: (600, 21) 传感器数据形状: (600, 19) 训练数据集形状: (31549, 600, 21) 标签形状: (31549,)
代码检查:
6. 数据可视化
- 可视化检查数据是否合理:
- 你可以通过可视化来进一步验证数据的合理性。例如,可以绘制一些切片的传感器数据,检查是否符合预期的趋势。
import matplotlib.pyplot as plt
plt.plot(X[0, :50]) # 可视化第一个切片的前50个时间步的数据
plt.show()
检查标签占比:
print(f"标签分布: {np.bincount(y)}")
输出:
标签分布: [ 9643 21906]