如何提高神经网络的准确性

我正在尝试构建一个简单的神经网络,用于将产品图片分类到不同的标签(产品类型)。例如,给定一张新的产品图片,判断它属于哪个产品类别(书籍、玩具、电子产品等)。

我有每种产品编号下的几张产品图片,每个产品编号在Excel表格中都有一个标签(即产品类型)。

以下是我的代码:

from sklearn.preprocessing import LabelEncoderfrom sklearn.cross_validation import train_test_splitfrom keras.models import Sequentialfrom keras.layers import Activationfrom keras.optimizers import SGDfrom keras.layers import Densefrom keras.utils import np_utilsfrom imutils import pathsimport numpy as npimport argparseimport cv2import osimport xlwtimport xlrdimport glob2import pickledef image_to_feature_vector(image, size=(32,32)):    return cv2.resize(image, size).flatten()def read_data(xls = "/Desktop/num_to_product_type.xlsx"):    book = xlrd.open_workbook(xls)    sheet = book.sheet_by_index(0)    d = {}    for row_index in xrange(1, sheet.nrows): # skip heading row        prod_type, prod_num = sheet.row_values(row_index, end_colx=2)        prod_type = unicode(prod_type).encode('UTF8')        produ_num = unicode(prod_num).encode('UTF8')        d[prod_num] = prod_type    return ddef main():    try:        imagePaths=[]        print("[INFO] describing images...")        for path, subdirs, files in os.walk(r'/Desktop/data'):            for filename in files:                imagePaths.append(os.path.join(path, filename))        files = glob2.glob('/Desktop/data/**/.DS_Store')        for i in files:            imagePaths.remove(i)      except:        pass    dd = read_data()     # initialize the data matrix and labels list    data = []    labels1 = []    for (i, imagePath) in enumerate(imagePaths):        image = cv2.imread(imagePath)        #print(image.shape)        subdir = imagePath.split('/')[-2]        for k, v in dd.items():            if k == subdir:                label = v                break        features = image_to_feature_vector(image)        data.append(features)        labels1.append(label)        # show an update every 1,000 images        if i > 0 and i % 1000 == 0:            print("[INFO] processed {}/{}".format(i, len(imagePaths)))    print("String Labels")    print(labels1)    # encode the labels, converting them from strings to integers    le = LabelEncoder()    labels = le.fit_transform(labels1)    print(labels)     d={}    d[labels[0]] = labels1[0]    for i in range(1,len(labels)-1):        if labels[i-1] != labels[i] and labels[i] == labels[i+1]:            d[labels[i]]  = labels1[i]    data = np.array(data) / 255.0    labels = np_utils.to_categorical(labels, 51)    print("To_Categorical")    print(labels)     print("[INFO] constructing training/testing split...")    (trainData, testData, trainLabels, testLabels) = train_test_split(        data, labels, test_size=0.25, random_state=42)    model = Sequential()    model.add(Dense(768, input_dim=3072, init="uniform",        activation="relu"))    model.add(Dense(384, init="uniform", activation="relu"))    model.add(Dense(51))    model.add(Activation("softmax"))    print("[INFO] compiling model...")    sgd = SGD(lr=0.125              )    model.compile(loss="categorical_crossentropy", optimizer=sgd,        metrics=["accuracy"])    model.fit(trainData, trainLabels, nb_epoch=50, batch_size=750)#     #Test the model    #show the accuracy on the testing set     print("[INFO] evaluating on testing set...")     (loss, accuracy) = model.evaluate(testData, testLabels,         batch_size=128, verbose=1)     print("[INFO] loss={:.4f}, accuracy: {:.4f}%".format(loss,         accuracy * 100))if __name__ == '__main__':    main()

这个神经网络是一个3-2-3-51的前馈神经网络。第0层包含3个输入。第1层和第2层是隐藏层,分别包含2个和3个节点。第3层是输出层,有51个节点(即51种产品类别类型)。然而,使用这种方法,我得到的准确率非常低,只有约45-50%。

我做错了什么吗?如何提高神经网络的准确性?我在某处读到可以通过“交叉验证和超参数调优”来实现,但具体该怎么做呢?抱歉,我对神经网络很新手,只是尝试一些新东西。谢谢。


回答:

在Keras中创建图像分类器时,我建议尝试使用卷积神经网络,因为它们在处理图像时效果更好。此外,层间归一化可以帮助提高训练过程中的准确性,从而改善验证/测试准确性。(这与训练前数据归一化的概念相同。)

要在Keras中添加卷积层,只需调用model.add(Conv2D(params)),而要在层间进行归一化,可以调用model.add(BatchNormalization())

卷积神经网络虽然更复杂,但更适合处理图像。它们的不同之处在于,卷积层在高层次上只是一个“迷你”神经网络,扫描图像的各个部分。这很重要,因为例如,你可以在两张图片中拥有完全相同的对象,但如果它们在图像中的位置不同,普通的神经网络会将其视为两个不同的对象,而卷积神经网络则能识别出它们是同一对象,只是出现在图像的不同位置…

因此,这个扫描图像部分(通常称为卷积核大小)的“迷你”神经网络更倾向于捕捉对象的相似特征。这些对象特征随后被训练到网络中,因此即使对象出现在图像的不同区域,也能更准确地识别为相同的东西。这是卷积神经网络在处理图像时表现更好的关键所在。

以下是基于NVIDIA模型架构的Keras 2中的一个基本示例,包括归一化…

        model = Sequential()        # 如果需要,裁剪图像以去除不相关的特征...        model.add(Cropping2D(cropping=((0, 0), (0,0)), input_shape=("your_input_shape tuple x,y,rgb_depth")))        model.add(Lambda(lambda x: (x - 128) / 128)) # 将所有像素归一化为0的均值 ±1        model.add(Conv2D(24, (2,2), strides=(2,2), padding='valid', activation='elu')) # 第1次卷积        model.add(BatchNormalization()) # 层间归一化        model.add(Conv2D(36, (2,2), strides=(2,2), padding='valid', activation='elu')) # 第2次卷积        model.add(BatchNormalization())        model.add(Conv2D(48, (1,1), strides=(2,2), padding='valid', activation='elu')) # 第3次卷积        model.add(BatchNormalization())        # model.add(Conv2D(64, (3,3), strides=(1,1), padding='valid', activation='elu')) # 第4次卷积        # model.add(BatchNormalization())        # model.add(Conv2D(64, (3,3), strides=(1,1), padding='valid', activation='elu')) # 第4次卷积        # model.add(BatchNormalization())        model.add(Dropout(0.5))        model.add(Flatten()) # 展平维度        model.add(Dense(100, activation='elu')) # 第1个全连接层        model.add(BatchNormalization())        model.add(Dropout(0.5))        model.add(Dense(51, activation= 'softmax')) # 输出标签的概率

最后,超参数调优只是调整批量大小、训练轮数、学习率等,以达到最佳结果。你所能做的就是实验,看看什么效果最好。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注