python实现LSTM(一):加载数据

# 1. 加载两个数据集
def load_data(path_1, path_0):
    # 加载标签为1的数据
    with h5py.File(path_1, 'r') as data_1:
        X_1 = np.array(data_1['X_all'])  # shape: (n, ch, time)
        y_1 = np.array(data_1['labelOne']).flatten()

    # 加载标签为0的数据
    with h5py.File(path_0, 'r') as data_0:
        X_0 = np.array(data_0['X_all'])  # shape: (n, ch, time)
        y_0 = np.array(data_0['labelZero']).flatten()

    print(f"原始维度: X_1.shape = {X_1.shape}, X_0.shape = {X_0.shape}")

    # 维度变换 -> (样本数, 时间点, 通道)
    X_1 = np.transpose(X_1, (0, 2, 1))  # (n, time, ch)
    X_0 = np.transpose(X_0, (0, 2, 1))

    print(f"转置后维度: X_1.shape = {X_1.shape}, X_0.shape = {X_0.shape}")

    # 合并数据
    X = np.concatenate([X_1, X_0], axis=0)
    y = np.concatenate([y_1, y_0])

    return X, y



✅ 函数结构总览(Python 和 MATLAB 的区别)

项目PythonMATLAB
函数定义def 函数名(参数):function [输出] = 函数名(输入)
函数结束缩进结束即表示结束(没有end关键字通过 end 明确结束
输入输出通过参数传入;返回值用 return输入和输出都要显式写在函数头上

这段函数功能:

从两个文件中读取数据,合并后返回合并的 X(特征)和 y(标签)

# 1. 加载两个数据集
def load_data(path_1, path_0):
  • def:define,定义函数

  • load_data:函数名,“加载数据”

  • path_1, path_0:函数的输入参数,分别表示标签为 1 和标签为 0 的文件路径


    # 加载标签为1的数据
    with h5py.File(path_1, 'r') as data_1:
  • with ... as ...:上下文管理器(自动打开并关闭文件,防止资源泄漏)

  • h5py.File():用 h5py 模块打开 .mat 文件(这个 .mat 文件必须是 v7.3 版本,也就是 基于 HDF5 格式的 .mat 文件。)

    • 'r':read,只读模式

  • data_1:变量名,代表打开的文件对象(里面可以按键访问


        X_1 = np.array(data_1['X_all'])  # shape: (n, ch, time)
        y_1 = np.array(data_1['labelOne']).flatten()
  • X_1:标签为1的数据特征

    • np.array(...):转成 NumPy 数组

    • 注意这里读取的维数会发生变化,我的原数据是(time,ch,n)

  • data_1['X_all']:从 .h5 文件中读取键名'X_all' 的内容

  • y_1:标签

    • 'labelOne':表示标签为1的分类

    • .flatten():将原始数据拉平成一维数组(比如(1000,1) 变成 (1000,)

Python 在读取过程中到底对数据“做了什么”?

原数据是(time,ch,n ), X_1   # shape: (n, ch, time)

 本质原因:维度解释方式不同(没做显式变换)

Python 并没有显式对数据“转换维度”,而是:

  • 按 C 语言风格(C-style,行优先)解释数据内存排列

  • 而 MATLAB 的 .mat 文件是按 Fortran-style(列优先) 保存的。

  • 所以维度变化的根源是:“读取时的内存解释方式不同”,数据在磁盘上是一样的字节顺序,但 Python 解释的维度顺序和 MATLAB 不一样!

     举例演示(2 × 3 × 4 小数组)

    MATLAB 中创建:

    A = reshape(1:24, [2, 3, 4]);
    size(A)  % 显示 (2, 3, 4)
    

    这是:

  • 第一维(行):2

  • 第二维(列):3

  • 第三维(页):4

  • 内存顺序是:先第1维(内存中优先变的是“行”维度(也就是第1维))再第2,再第3。

    内存顺序(Fortran-style,列优先):

    第1页(第3维 = 1):
    列1     列2     列3
    1   →   3   →   5
    2       4       6
    
    第2页(第3维 = 2):
    7       9       11
    8       10      12
    
    第3页:
    13      15      17
    14      16      18
    
    第4页:
    19      21      23
    20      22      24
    

    这就是 MATLAB 的 A(:,:,1)A(:,:,4)


    ✅ 二、Python 中读取

    with h5py.File('file.mat', 'r') as f:
        A = np.array(f['A'])
    print(A.shape)  # (4, 3, 2)
    

    Python 把它当成 (4 页, 3 列, 2 行) 读取,也就是 (4, 3, 2),换句话说,维度顺序倒过来了。

     内存按 C-style(行优先)来解释:

    也就是说,Python 读取后,数组 A 的排布是这样的(按照原 MATLAB 的内存顺序):

    A[0, :, :] =  # 第0页(其实是 MATLAB 的第4页)
    [[19, 20],
     [21, 22],
     [23, 24]]
    
    A[1, :, :] =  # MATLAB 的第3页
    [[13, 14],
     [15, 16],
     [17, 18]]
    
    A[2, :, :] =  # MATLAB 的第2页
    [[7, 8],
     [9, 10],
     [11, 12]]
    
    A[3, :, :] =  # MATLAB 的第1页
    [[1, 2],
     [3, 4],
     [5, 6]]
    

    你可以看到,顺序倒了!


    # 加载标签为0的数据
    with h5py.File(path_0, 'r') as data_0:
        X_0 = np.array(data_0['X_all'])  # shape: (n, ch, time)
        y_0 = np.array(data_0['labelZero']).flatten()
  • 同样结构:读取标签为 0 的数据和标签

  • labelZero:标签为 0 的样本

  • .flatten():将原始数据拉平成一维数组(比如(1000,1) 变成 (1000,)

  • (1000, 1)(1000,) 好像差不多,都是“1000 个数”,但实际上它们的结构是完全不同的,尤其是在 NumPy 和模型训练中很关键。

    (1000, 1) 的结构:

    这是一个二维数组,有 1000 行,1 列,每个元素还嵌套在一个小列表里:

    [[1],
     [2],
     [3],
     ...
     [1000]]
    

     shape 是 (1000, 1)二维结构

    (1000,) 的结构:

    这是一个 一维数组,直接就是 1000 个数,排成一条“线”:

    [1, 2, 3, ..., 1000]
    

     shape 是 (1000,)一维结构

    重点在于结构维度

  • (1000, 1) 是二维,适合做矩阵运算、广播等;

  • (1000,) 是一维,更简洁,很多函数(尤其是模型的标签 y)只接受一维向量作为输入

  •  模型为什么更喜欢 (1000,)?例如,在训练神经网络时:

  • model.fit(X, y)
    

    如果 y(1000, 1),模型可能认为你有 1000 个样本,每个标签是一个向量,但你只是要给一个标签 [1, 0, 1, ...],所以一维更清晰。


    print(f"原始维度: X_1.shape = {X_1.shape}, X_0.shape = {X_0.shape}")
  • f"...":格式化字符串,{} 里能放变量

  • .shape:查看数组的维度,方便 debug


    # 维度变换 -> (样本数, 时间点, 通道)
    X_1 = np.transpose(X_1, (0, 2, 1))  # (n, time, ch)
    X_0 = np.transpose(X_0, (0, 2, 1))
  • np.transpose(arr, axes):交换维度顺序

    • 原来是 (n, ch, time) ➜ 变成 (n, time, ch)

    •  (0, 2, 1) 的意思是:

      新的维度位置对应旧的维度编号原来的含义现在的新顺序含义
      第0维0样本 n样本 n
      第1维2通道 ch时间 time
      第2维1时间 time通道 ch

      也就是说:
      把原来的 (n, ch, time) → 变成了 (n, time, ch),适配模型的输入需求:

      (batch_size, time_steps, channels)
      
    • 每个样本是一个时间序列(time_steps 个时间点)

    • 每个时间点是一个向量(channels 个通道)

    • 就是把原来的 (样本数, 通道, 时间) → 转换成了 (样本数, 时间, 通道),便于送入模型。


    print(f"转置后维度: X_1.shape = {X_1.shape}, X_0.shape = {X_0.shape}")
  • 再次打印,确认转置是否成功


    # 合并数据
    X = np.concatenate([X_1, X_0], axis=0)
    y = np.concatenate([y_1, y_0])
  • np.concatenate([A, B], axis=0):在第 0 个维度上拼接两个数组(样本数方向)

  • 所以:把标签为 1 和标签为 0 的样本拼到一起

  • X:拼接后的数据,y:拼接后的标签


    return X, y
  • return:返回结果

  • 这里返回两个变量:特征 X 和 标签 y

def 开头,缩进块里做事,return 返回值就结束。
不用写输入输出名在开头,返回值谁接谁用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值