You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:解决TensorFlow中无法将列表转换为张量的问题(CSV数据集适配)

解决TensorFlow中列表转张量失败及LSTM输入适配问题

我看了你的代码和问题描述,核心问题出在数据预处理的方式不对,导致最终的输入数据结构不符合LSTM的要求,同时还有一些未定义的模型参数需要修正。下面一步步帮你解决:

问题根源分析

  1. 你当前处理X的方式:把三个sensor列的列表组合成np.matrix后,每个元素依然是Python列表,得到的是一个包含列表的矩阵,而不是TensorFlow能识别的数值型三维数组。
  2. LSTM要求输入形状是(样本数, 时间步长, 特征数),但你现在的X结构完全不匹配。
  3. 模型定义里的max_sequence_length、embed_dim、pre_trained_wv等参数都没有定义,运行时会直接报错。

分步解决方案

1. 修正数据预处理流程

首先,我们需要把三个sensor的数值列表合并成一个三维数组:

  • 每个样本对应一组sensor1、sensor2、sensor3的列表,假设每个sensor列表的长度是相同的(比如都是N个时间步),那么每个样本的形状应该是(N, 3),整个训练集的形状就是(样本数, N, 3)。
  • 用np.stack来合并三个sensor的列表,而不是用np.matrix。

2. 定义模型所需参数

需要明确LSTM的时间步长(即每个sensor序列的长度)、特征数(这里是3,对应三个传感器),还有输出类别数(根据你的categoria列的独热编码结果,假设是2类)。

3. 调整模型输入形状

根据预处理后的三维输入,模型的输入形状应该设为(时间步长, 特征数),而不是之前的(max_sequence_length,)。

4. 修复预测环节的错误

预测部分的new_text处理逻辑有问题,需要调整为和训练数据一致的预处理方式。

修改后的完整代码

import sys
import numpy as np
import pandas as pd
import os
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.layers import Dense, LSTM, Input
from tensorflow.keras.preprocessing.sequence import pad_sequences

# -------------------------- 数据预处理 --------------------------
df = pd.read_csv('set1.csv')

# 将字符串形式的列表转为Python列表
s1 = df["sensor1"].apply(eval)
s2 = df["sensor2"].apply(eval)
s3 = df["sensor3"].apply(eval)

# 合并三个传感器数据为三维数组:(样本数, 时间步长, 特征数)
# 先检查所有序列长度是否一致,这里假设都是相同长度,如果有不同可以用pad_sequences补全
sequence_length = len(s1.iloc[0])
X = np.stack([np.array(s1.tolist()), np.array(s2.tolist()), np.array(s3.tolist())], axis=-1)

# 处理标签:独热编码
Y = pd.get_dummies(data=df.categoria).values
num_classes = Y.shape[1]

# 划分训练测试集
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.1, random_state=42)

print("Train Shape:", X_train.shape, Y_train.shape)  # 应该是 (样本数, sequence_length, 3)
print("Test Shape:", X_test.shape, Y_test.shape)

# -------------------------- 模型定义 --------------------------
# 定义模型参数
sequence_length = X_train.shape[1]
feature_num = X_train.shape[2]
lstm_units = 64  # 可以根据需求调整
epochs = 10
batch_size = 32
filename = 'lstm_gesture_weights.h5'

def build_model():
    # 输入形状适配LSTM:(时间步长, 特征数)
    model_input = Input(shape=(sequence_length, feature_num), name="input")
    # LSTM层
    lstm = LSTM(lstm_units, dropout=0.2, recurrent_dropout=0.2, name="lstm")(model_input)
    # 输出层:根据类别数设置Dense单元数
    model_output = Dense(num_classes, activation='softmax', name="softmax")(lstm)
    model = Model(inputs=model_input, outputs=model_output)
    return model

model = build_model()
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
print(model.summary())

# -------------------------- 模型训练/加载 --------------------------
if not os.path.exists('./{}'.format(filename)):
    hist = model.fit(
        X_train, Y_train,
        validation_data=(X_test, Y_test),
        epochs=epochs,
        batch_size=batch_size,
        shuffle=True,
        verbose=1)
    model.save_weights(filename)
    
    # 绘制损失曲线
    plt.figure()
    plt.plot(hist.history['loss'], lw=2.0, color='b', label='train')
    plt.plot(hist.history['val_loss'], lw=2.0, color='r', label='val')
    plt.title('Classificador de Gestos')
    plt.xlabel('Epochs')
    plt.ylabel('Cross-Entropy')
    plt.legend(loc='upper right')
    plt.show()

    # 绘制准确率曲线
    plt.figure()
    plt.plot(hist.history['accuracy'], lw=2.0, color='b', label='train')
    plt.plot(hist.history['val_accuracy'], lw=2.0, color='r', label='val')
    plt.title('Classificador de Gestos')
    plt.xlabel('Epochs')
    plt.ylabel('Acurácia')
    plt.legend(loc='upper left')
    plt.show()
else:
    model.load_weights('./{}'.format(filename))
    scores = model.evaluate(X_test, Y_test, verbose=0, batch_size=batch_size)
    print("Acc: %.2f%%" % (scores[1]*100))

# -------------------------- 预测环节 --------------------------
while True:
    sentence = input("input> ")
    if sentence == "exit":
        break
    # 这里假设输入的是类似csv中的字符串列表,比如"[1,2,3],[4,5,6],[7,8,9]"
    # 需要根据实际输入格式调整预处理逻辑
    try:
        # 分割三个传感器的数据
        s1_input, s2_input, s3_input = sentence.split(',')
        # 转为列表并转成数组
        s1_input = np.array(eval(s1_input.strip()))
        s2_input = np.array(eval(s2_input.strip()))
        s3_input = np.array(eval(s3_input.strip()))
        # 调整形状为(1, sequence_length, 3),匹配模型输入
        new_data = np.stack([s1_input, s2_input, s3_input], axis=-1).reshape(1, sequence_length, 3)
        # 预测
        sentiment = model.predict(new_data, batch_size=1, verbose=2)[0]
        pred_class = np.argmax(sentiment)
        pred_proba = "%.2f%%" % (sentiment[pred_class]*100)
        if pred_class == 0:
            print("movimento para direita => ", pred_proba)
        else:
            print("movimento para esquerda => ", pred_proba)
    except Exception as e:
        print(f"输入格式错误,请按照示例输入:例如 [1,2,...,N],[3,4,...,N],[5,6,...,N],错误信息:{e}")

额外注意事项

  • 如果你的sensor序列长度不一致,需要在预处理时用pad_sequences统一长度,比如:
    # 统一序列长度为最长的那个
    max_len = max([len(s) for s in s1])
    s1_padded = pad_sequences(s1.tolist(), maxlen=max_len, dtype='float32')
    s2_padded = pad_sequences(s2.tolist(), maxlen=max_len, dtype='float32')
    s3_padded = pad_sequences(s3.tolist(), maxlen=max_len, dtype='float32')
    X = np.stack([s1_padded, s2_padded, s3_padded], axis=-1)
    
  • 模型的损失函数用categorical_crossentropy更适合多分类(这里是2类),之前的binary_crossentropy也可以,但categorical_crossentropy更标准。
  • 确保导入了所有需要的库,之前的代码里缺少pandas、os、matplotlib等的导入。

内容的提问来源于stack exchange,提问作者PALTJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 18:59:05