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

TensorFlow与词嵌入报错:TypeError: unhashable type: 'numpy.ndarray'修复

解决RNN问答预测代码中的TypeError: unhashable type: 'numpy.ndarray'错误

先给你吃个定心丸:这个错误和unstack操作完全无关,问题出在你对TensorFlow中feed_dict的用法理解出现了偏差,咱们一步步来修复:

错误根源分析

你在sess.run()里写的feed_dict完全搞反了规则:

  • feed_dict的键必须是TensorFlow的占位符(placeholder)或者变量(Variable),而且必须是可哈希的类型;
  • 你现在把tf.nn.embedding_lookup(W, x2)这种Tensor运算结果当成键,同时还把numpy数组y直接作为键——numpy数组是不可哈希的类型,这直接触发了TypeError。

另外,你还跳过了最基础的一步:没有定义输入数据的占位符,TensorFlow根本不知道该接收什么样的输入数据。


具体修复步骤

1. 先定义输入占位符

在graph初始化的最开头,先定义好输入序列x2和目标输出y的占位符,维度根据你的任务调整(比如输入是固定长度的问答序列,目标是单个词的索引):

tf.reset_default_graph()
g = tf.Graph()
with g.as_default():
    # 先定义占位符!根据你的实际数据维度调整
    sequence_length = 10  # 假设你的输入序列长度是10,改成你自己的数值
    x2 = tf.placeholder(tf.int32, [None, sequence_length])  # 输入序列的词索引数组
    y = tf.placeholder(tf.int32, [None])  # 目标输出的词索引(单个词)
    
    # 后面是你原来的embedding、RNN定义代码...

2. 修正feed_dict的写法

feed_dict的键是刚才定义的占位符,值是你生成的numpy数组(也就是np.array(list(vocab_processor.transform([s])))得到的结果),不需要在feed_dict里做embedding_lookup——因为你已经在graph里用tf.nn.embedding_lookup(W, x2)处理了输入:

# 假设你已经生成了x2_numpy和y_numpy这两个numpy数组
_,loss, pred_ = sess.run([optimizer, cost, pred], 
                         feed_dict = {x2: x2_numpy, y: y_numpy})

3. 修正损失函数的维度匹配

你的损失函数用了tf.nn.l2_loss(pred-y),但pred是embedding维度的Tensor,而y是词索引,需要先转成embedding向量才能计算损失:

# 在定义cost之前,先把y转成embedding向量
y_embedding = tf.nn.embedding_lookup(W, y)
cost = tf.reduce_mean(tf.nn.l2_loss(pred - y_embedding))

4. 其他优化建议

  • 你的NHIDDEN()返回1,这个隐藏层维度太小了,实际任务里建议调大到128/256,不然模型根本学不到有效特征;
  • 确保vocab_size、embedding_dim等参数和你的预训练词向量完全匹配,避免维度不兼容的问题。

修正后的完整核心代码片段

import tensorflow.contrib as ct
def NHIDDEN(): return 128  # 调大隐藏层维度
tf.reset_default_graph()
g = tf.Graph()
with g.as_default():
    # 定义输入占位符
    sequence_length = 10  # 根据你的数据调整
    x2 = tf.placeholder(tf.int32, [None, sequence_length])
    y = tf.placeholder(tf.int32, [None])
    
    # RNN输出层权重和偏置
    weights = {
        'out': tf.Variable(tf.random_normal([NHIDDEN(), embedding_dim]))
    }
    biases = {
        'out': tf.Variable(tf.random_normal([embedding_dim]))
    }
    
    with tf.name_scope("embedding"):
        W = tf.Variable(tf.constant(0.0, shape=[vocab_size, embedding_dim]), trainable=False, name="W")
        embedding_placeholder = tf.placeholder(tf.float32, [vocab_size, embedding_dim])
        embedding_init = W.assign(embedding_placeholder)
        preimage = tf.nn.embedding_lookup(W, x2)
    
    # 重塑输入并构建RNN
    x_unstack = tf.unstack(preimage, axis=1)  # 明确指定axis,避免歧义
    rnn_cell = ct.rnn.MultiRNNCell([ct.rnn.BasicLSTMCell(NHIDDEN()), ct.rnn.BasicLSTMCell(NHIDDEN())])
    outputs, states = ct.rnn.static_rnn(rnn_cell, x_unstack, dtype=tf.float32)
    
    # 取最后一个输出做预测
    pred = tf.matmul(outputs[-1], weights['out']) + biases['out']
    
    # 修正损失函数
    y_embedding = tf.nn.embedding_lookup(W, y)
    cost = tf.reduce_mean(tf.nn.l2_loss(pred - y_embedding))
    optimizer = tf.train.AdamOptimizer(learning_rate=0.001).minimize(cost)
    
    step = 0
    acc_total = 0
    loss_total = 0
    
    # 假设你已经加载了预训练词向量到embedding_vectors,生成了x2_numpy和y_numpy
    with tf.Session(graph = g) as sess:
        sess.run(tf.global_variables_initializer())
        # 初始化预训练词向量
        sess.run(embedding_init, feed_dict={embedding_placeholder: embedding_vectors})
        
        while step < 100:  # 改成你的训练迭代次数
            _,loss, pred_ = sess.run([optimizer, cost, pred], 
                                     feed_dict = {x2: x2_numpy, y: y_numpy})
            loss_total += loss
            print("Step {}, Avg Loss = {:.6f}".format(step, loss_total/(step+1)))
            step += 1
        print ("Finished Optimization")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:30:58