关于模式识别的 ANN

数据挖掘 机器学习 神经网络 分类 深度学习 喀拉斯
2022-02-04 15:40:50

我一直在尝试使用 keras 应用一个简单的神经网络来预测一个数字序列,规则是如果输入整数是奇数,它应该是 4,如果它是偶数,它应该是 2。但是神经网络卡在 60 % 准确率。有谁知道这个问题的解决方案?

from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout

from keras.layers.normalization import BatchNormalization

from sklearn.model_selection import cross_val_score
from keras.wrappers.scikit_learn import KerasClassifier

import numpy as np


def gen(x):
    if (x%2==0):
        return 2;
    else:
        return 4;


a = []           
for i in range(1,100001):
    a.append([i,gen(i)])

a = np.array(a)


x = a[:,0:1]
y = a[:,1:2]


def MakeClassifier():
    network_classifier = Sequential()
    network_classifier.add(Dense(units=2,kernel_initializer="uniform",activation="relu",input_dim=1)) #Hidden Layer1 taking into account number of inputs(independant variables(x)
    network_classifier.add(BatchNormalization())
    network_classifier.add(Dense(units=1,kernel_initializer="uniform",activation="sigmoid"))#OutPutLayer

    network_classifier.compile(optimizer="adam",loss="binary_crossentropy",metrics=["accuracy"])#If multicategorical then categorical_crossentropy
    return network_classifier

classifier = KerasClassifier(build_fn= MakeClassifier , batch_size = 10 , epochs = 1000)

classifier.fit(x,y,epochs=100,batch_size=1000)

print(classifier.predict([[6],[7]])) #Should Predict 2 and 4
1个回答

这个结果有两个可能的原因:

  • 训练示例数量少
  • 使用没有批量标准化的密集层

你有一个相对较深的网络,你的训练集很小。在这种情况下,如果您运行模型太多次,您肯定会过度拟合训练数据。原因是只要你有一个强大的模型可以学习复杂的功能,并且如果你提供少量的训练示例,它就有能力拟合数据而不是学习它。假设您在微积分中有一个拟合问题,并且您有 4 个点,并且您还有四次多项式。在这种情况下,您可以准确地拟合数据而不会出现任何错误,但关键是您正在拟合它,而不是学习它。在您的情况下,您的模型很强大,它试图拟合数据,而不是学习数据。解决方法是提供足够的训练数据。

您的模型无法学习的原因是您在没有批量标准化的情况下堆叠密集层。每次更新权重时,深层的输出都会发生变化,这会导致协变量偏移。为避免此问题,请使用批量标准化。

作为您的解决方案,我建议您只放置两个隐藏层并操纵这些层中的单元数量并提供更多训练示例。您的任务可以通过两个隐藏层网络轻松学习。


在挣扎了大约一天之后,我终于想表达我对这个问题的看法。根据问题,可以使用机器学习或其他技术来解决它们。机器学习问题是那些您无法定义适当的函数来将输入映射到输出的问题,或者这样做可能非常困难。只要你有这个函数,它就可以作为假设,机器学习算法的最终目标。我努力尝试并在这段代码上投入了很多时间,我得到了相同的结果。什么都学不会。我已经尝试了大约一天,但仍然没有看到任何进展。要解释原因,数据太难学习了!为了想象它有多么困难,我建议你把数字从一到十写成一条直线,并在连续的数字之间划一条线。这些数字是无穷无尽的,因此您将无法一概而论,因为要找到的边界仅适用于两个相邻数字。这意味着,如果您使用当前功能,您将无法分离、学习您的数据。我试图以某种方式进行特征工程并使用以下代码来解决问题:

import keras
import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers.normalization import BatchNormalization 
from keras import regularizers 
from keras.optimizers import Adam

def gen(x):
    if (x % 2 == 0):
        return 0; # represents 2
    else:
        return 1; # represents 4


a = []           
for i in range(1,100001):
    temp = np.random.randint(0, 10000000)
    a.append([temp, temp ** 2, temp ** 3, temp ** 4, gen(temp)])

a = np.array(a)


x = a[:, 0: a.shape[1] - 1]
y = a[:, a.shape[1] - 1:]

mean_of_x = np.mean(x, axis = 0, keepdims = True)
std_of_x = np.std(np.float64(x), axis = 0, keepdims = True)
x = (x - mean_of_x) / std_of_x

n_classes = 2
y = keras.utils.to_categorical(y, 2)

percentage = 95 / 100
limit = int(percentage * x.shape[0])

x_train = x[: limit, :]
y_train = y[: limit, :]

x_test = x[limit: , :]
y_test = y[limit: , :]

x_train.shape

model = Sequential()
model.add(Dense(1000, activation='relu', input_shape=(x_train.shape[1],)))
model.add(BatchNormalization())
# model.add(Dropout(0.5))
model.add(Dense(1000, activation='relu'))
model.add(BatchNormalization())
# model.add(Dropout(0.5))

model.add(Dense(n_classes, activation='softmax'))

model.summary()

model.compile(loss = 'categorical_crossentropy', optimizer = keras.optimizers.Adam(lr = 0.0001, decay = 1.5), metrics=['accuracy'])

model.fit(x_train, y_train, batch_size = 128, epochs = 2000, verbose = 1, validation_data=(x_test, y_test), shuffle = True,
          class_weight = {0: 10, 1: 1})

如您所见,上面的代码使用了高阶多项式。令人惊讶的是,这里也没有看到任何进展。该模型在更高维度的先前特征中存在上述问题。这就是为什么学习也不会在这里发生的原因。

这里的重点是,尽管您无法使用当前特征、数字本身或其高阶多项式来学习,但您已经有了解决问题的方法。不要将数字本身传递给学习问题,而是传递当前数字的模二。这个功能非常容易学习。您可能只需要一个单元。