TensorFlow报错‘Dst tensor is not initialized’,CNN训练进程被终止
解决TensorFlow进程被终止及内存相关错误的方案
首先,你的核心问题出在模型结构设计严重不合理和数据处理逻辑错误,这两个问题共同导致了内存耗尽,进而触发进程被Killed以及TensorFlow的初始化错误。下面一步步拆解问题并给出修复方案:
1. 超大Dense层直接导致内存爆炸
看你的模型最后两个Dense层:
model.add(Dense(95692,activation='sigmoid')) model.add(Dropout(0.2)) model.add(Dense(95692,activation='sigmoid'))
这完全不合理!我们来算一下参数规模:
- 前面Flatten之后的输出维度:假设经过Embedding(300,128)和三层Conv1D后,最后Conv1D(16,3,padding='same')的输出是
(样本数, 300, 16),Flatten后每个样本是300*16=4800维。 - 第一个Dense(95692)的参数数量:
4800*95692 + 95692 ≈ 4.6亿 - 第二个Dense(95692)的参数数量:
95692*95692 + 95692 ≈ 9万亿
哪怕你的GPU有93GB内存,也根本扛不住这么恐怖的参数规模,直接会把内存占满导致进程被系统杀死。
修复方案:
你的任务是回归(预测0-1之间的score),最后一层应该是单输出的Dense层,中间的Dense层用合理的神经元数量(比如128、64这种量级):
model.add(Flatten()) model.add(Dropout(0.2)) model.add(Dense(128,activation='relu')) # 用ReLU作为中间层激活更合理 model.add(Dropout(0.2)) model.add(Dense(64,activation='relu')) model.add(Dense(1,activation='sigmoid')) # 最后输出单个score值
2. 数据处理逻辑错误,加剧内存浪费和维度不匹配
你的文本处理部分完全搞混了texts_to_matrix和texts_to_sequences的用法:
x_train = pad_sequences(tok.texts_to_matrix(train[['comment']], mode='count'), maxlen=max_length, padding='post')
texts_to_matrix返回的是词袋模型矩阵,形状为(样本数, vocab_size)(这里是(N,20000)),每个样本是20000维的向量,根本不需要用pad_sequences处理(pad_sequences是用来处理变长整数序列的)。- 而你的模型开头用了
Embedding层,Embedding层需要的输入是整数序列(每个样本是长度为max_length的整数列表,代表每个词的索引),所以应该用texts_to_sequences而不是texts_to_matrix。
另外,你的标签处理也绕了弯路,还导致形状错误:
y_train = np.array([[float(d)] for d in train[['score']].pop('score')]).T
这样得到的y_train形状是(1, N),但Keras的fit方法期望标签形状是(N, 1),会导致训练时的维度不匹配问题。
修复方案:
修改文本和标签的处理代码:
# 处理文本:生成整数序列并填充到固定长度 x_train = pad_sequences(tok.texts_to_sequences(train['comment']), maxlen=max_length, padding='post') x_test = pad_sequences(tok.texts_to_sequences(test['comment']), maxlen=max_length, padding='post') # 处理标签:直接转成(N,1)的形状 y_train = np.array(train['score']).reshape(-1, 1) y_test = np.array(test['score']).reshape(-1, 1)
3. 其他优化建议
- 如果你确实想用词袋模型而不是序列输入,那应该去掉
Embedding层,直接把texts_to_matrix的输出喂给Dense层,但这样的话模型结构要完全调整,不过对于文本任务,序列输入+Embedding的效果通常更好。 - 可以在训练时加上
batch_size参数,比如model.fit(..., batch_size=32),避免一次性加载所有数据到内存,进一步降低内存压力。
修改后的完整模型示例
# 数据处理部分修改后 comments = pd.read_csv('set1.tsv', sep='\t', index_col=0) annotations = pd.read_csv('set2.tsv', sep='\t') labels = annotations.groupby('rev_id')['score'].mean() labels = pd.DataFrame(data=labels.values, columns=['score']) scaler = MinMaxScaler(feature_range=(0, 1)) labels = 1-(scaler.fit_transform(labels)) comments['score'] = labels comments['comment'] = comments['comment'].apply(lambda x: x.replace("NEWLINE_TOKEN", " ")) comments['comment'] = comments['comment'].apply(lambda x: x.replace("TAB_TOKEN", " ")) comments = comments.reset_index() vocab_size = 20000 max_length = 300 tok = Tokenizer(num_words=vocab_size) tok.fit_on_texts(comments['comment']) train = comments.query("split=='train'") test = comments.query("split=='test'") x_train = pad_sequences(tok.texts_to_sequences(train['comment']), maxlen=max_length, padding='post') y_train = np.array(train['score']).reshape(-1, 1) x_test = pad_sequences(tok.texts_to_sequences(test['comment']), maxlen=max_length, padding='post') y_test = np.array(test['score']).reshape(-1, 1) # 模型结构修改后 embedding_vecor_length = 128 model = Sequential() model.add(Embedding(vocab_size, embedding_vecor_length, input_length=max_length)) model.add(Convolution1D(64, 3, padding='same', activation='relu')) model.add(Convolution1D(32, 3, padding='same', activation='relu')) model.add(Convolution1D(16, 3, padding='same', activation='relu')) model.add(Flatten()) model.add(Dropout(0.2)) model.add(Dense(128, activation='relu')) model.add(Dropout(0.2)) model.add(Dense(64, activation='relu')) model.add(Dense(1, activation='sigmoid')) tensorBoardCallback = TensorBoard(log_dir='./logs', write_graph=True) model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) model.fit(x_train, y_train, epochs=3, batch_size=32, callbacks=[tensorBoardCallback])
按照上面的修改,你应该能解决内存耗尽的问题,TensorFlow的初始化错误也会随之消失。
内容的提问来源于stack exchange,提问作者alienboy
相关产品推荐
相关产品推荐

