【发布时间】:2021-09-29 16:11:34
【问题描述】:
我正在使用 CNN 对 DNA 序列进行二元分类,但无论我如何重构我的数据/网络,我都无法让二维二元分类 CNN 工作。我可以对标签进行一次热编码,并使用具有二元分类损失函数的 2 个神经元、softmax、密集层,但准确率仅徘徊在 50% 左右,更不用说完全错误地结合使用激活和损失。
数据是 5000 个 DNA 序列(分成 4500 个序列/500 个验证),每个 1000 个核苷酸长,经过标记化和一个热编码为 4x1000 矩阵(A、T、C、G)。标签只是 0/1 来表示它们是否有特定的主题。
# Returns Pandas dataframe of names, sequences, and labels that I generated
totalSeqs = GenSeqs()
# Splitting data and labels in to train/validation sets
x_tr, x_val, y_tr, y_val = train_test_split(totalSeqs.Sequences.tolist(), totalSeqs.Labels.tolist(), test_size = 0.1)
x_tr, x_val, y_tr, y_val = np.array(x_tr), np.array(x_val), np.array(y_tr), np.array(y_val)
#Tokenizing sequences
tk = Tokenizer(num_words=None, char_level=True)
tk.fit_on_texts(x_tr)
tokenTrain = tk.texts_to_sequences(x_tr)
# One hot encoding tokenized sequences
oneHotTrain = OneHot(tokenTrain)
# Resizing to fit Conv2D and making sure there aren't any array/list conflicts
# Saw someone else had this issue, so I went overboard on preventing it
oneHotTrain = np.array(oneHotTrain).reshape(-1, 4500, 1000, 4)
for x in oneHotTrain:
x = np.array(x)
for i in x:
i = np.array(i)
for j in i:
j = np.array(j)
print(oneHotTrain.shape)
trainLabels = np.array(y_tr).reshape(-1, 4500, 1)
for x in trainLabels:
x = np.array(x)
for i in x:
i = np.array(i)
for j in i:
j = np.array(j)
print(trainLabels.shape)
这都会输出序列的形状 (1, 4500, 1000, 4) 和标签的形状 (1, 4500, 1)。据我了解,这些是正确的形状,但很难获得有关标签形状的准确信息。
从这里,我创建了 CNN:
model = Sequential()
model.add(Conv2D(32, 4, activation='relu', input_shape = (4500, 1000, 4)))
model.add(MaxPooling2D(2))
model.add(Conv2D(64, 3, activation='relu'))
model.add(MaxPooling2D(2))
model.add(Flatten())
model.add(Dense(64, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
model.summary()
final = model.fit(oneHotTrain, trainLabels, batch_size = 100, epochs = 3, verbose = 1)
作为参考,这是我使用的一个热编码功能:
def OneHot(data):
num_classes = 4
new_data = []
for x in data:
class_vector = np.array(x)
categorical = np.zeros(class_vector.shape+(num_classes,))
for c in range(1,5,1):
categorical[np.where(class_vector == c)]=np.array([1 if i == c else 0.0 for i in range(1,5,1)])
new_data.append(categorical)
return new_data
它的输出结果很好,我用来生成“DNA”的函数只创建了 1000 个字符长且仅由 A/T/C/G 组成的序列。我已经通过从 Tokenizer 输出信息、它们的长度等验证了所有这些,无论哪种方式,最后一个热矩阵结果都很好,所以我认为问题不存在,甚至不存在于一个热函数本身.
我的假设是错误存在于 CNN 架构/参数或数据/标签形状的某个地方,但如果我可能遗漏了什么。有什么建议吗?
【问题讨论】:
-
(1, 4500, 1) 不是正确的形状,样本维度是第一个,然后是类的#,无论如何这是正确的。
-
准确地说 (4500, 1) 对您的标签来说是正确的。
-
@Dr.Snoopy 好的,但是每当我将标签形状更改为 (4500, 1) 时,我都会收到错误消息:“ValueError:数据基数不明确:x 大小:1 y 大小:4500 请提供共享相同第一维度的数据。”
-
你还需要确保训练数据的格式正确,它可能有同样的问题。
-
如果我在训练数据的开头去掉1维,我得到错误:“ValueError: Input 0 of layer sequence_1 is in compatible with the layer: : expected min_ndim=4, found ndim=3。收到的完整形状:[100, 1000, 4]"。
标签: python numpy tensorflow keras conv-neural-network