#python #machine-learning #keras #conv-neural-network
Вопрос:
В настоящее время я пытаюсь сравнить производительность моего набора данных между различными типами NN и, таким образом, сначала я пытаюсь использовать Сверточную нейронную сеть (CNN).
К сожалению, я получаю ошибку IndexError: tuple index out of range
для строки model.add(Dense(y_train.shape[1], activation='softmax'))
в приведенном ниже коде.
Входные формы для X_train и y_train следующие:
X_train : (89680, 25)
y_train : (89680,)
Результат dataset.head()
выглядит следующим образом:
FrameLen_0 FrameLen_1 FrameCapLen_0 FrameCapLen_1 ... TLSRecordContentType_0 TLSRecordLen_0 TLSAppData_0 PacketTime_0
0 116 66.0 116 66.0 ... 23.0 45.0 45 0.000028
1 116 66.0 116 66.0 ... 23.0 45.0 45 0.000026
2 116 66.0 116 66.0 ... 23.0 45.0 45 0.000024
3 116 66.0 116 66.0 ... 23.0 45.0 45 0.000025
4 116 66.0 116 66.0 ... 23.0 45.0 45 0.000028
[5 rows x 25 columns]
Я не могу понять, почему я получаю эту ошибку. Вот код:
import os
import ast
import numpy as np
import pandas as pd
import tensorflow as tf
import matplotlib.pyplot as plt
import itertools
import keras.backend as K
import scipy
import scipy.sparse as sp
import seaborn as sn
import random
from string import ascii_uppercase
from keras.callbacks import EarlyStopping
from keras.models import Sequential
from keras.layers import Dense, LSTM, Dropout, Activation, Flatten
from keras.layers import Convolution2D, Conv1D, Conv2D, MaxPooling2D, LeakyReLU, ELU, MaxPooling1D
from keras.utils import np_utils, to_categorical, plot_model
from keras import metrics
from keras.optimizers import SGD, Adam, Adadelta
from sklearn.model_selection import train_test_split
from sklearn.feature_selection import SelectKBest, f_classif
from sklearn.utils import class_weight
from skmultilearn.model_selection import iterative_train_test_split
from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler, OneHotEncoder, LabelEncoder, Normalizer
from itertools import tee # finally! I found something useful for it
from sklearn.metrics import confusion_matrix, classification_report, accuracy_score
import matplotlib.font_manager as fm
from matplotlib.collections import QuadMesh
SEED = 12345
random.seed(SEED) # for reproducibility
def bytes_to_len_bytes(s):
try:
s = s.replace(':', ' ')
l = len(bytes.fromhex(s))
except:
l = 0
return l
def get_class_counts(df, target):
grp = df.groupby(target).nunique()
return {key: grp[key] for key in list(grp.keys())}
def get_class_proportions(df, target):
class_counts = get_class_counts(df, target)
return {val[0]: round(val[1] / df.shape[0], 4) for val in class_counts.items()}
######
# Pre-preprocessing
dataset = pd.read_csv('dataset.csv')
target = dataset.pop('Movement')
others = dataset[['Distance', 'Speed', 'Delay', 'Loss']]
dataset.drop(['Distance', 'Speed', 'Delay', 'Loss'], axis=1, inplace=True) # Drop other classes for now..
dataset['Payload_0'] = dataset['Payload_0'].apply(lambda x: bytes_to_len_bytes(x)) #.astype(str)
dataset['TLSAppData_0'] = dataset['TLSAppData_0'].apply(lambda x: bytes_to_len_bytes(x)) #.astype(str)
print(dataset.head())
# Use 20% of samples for testing (test_size=0.2)
X_train, X_test, y_train, y_test = train_test_split(dataset, target, shuffle=True, random_state=SEED, stratify=target, test_size=0.2)
# Check the proportions are even from stratification
# print("train data proportions", get_class_proportions(X_train, target))
# print("test data proportions", get_class_proportions(X_test, target))
# Normalise the training set and testing set individually
# to ensure truly *unseen* nature of test dataset
sc = RobustScaler().fit(X_train) # MinMaxScaler() # We use robust scaler to reduce influence of possible outliers
X_train_normalised = sc.transform(X_train)
X_test_normalised = sc.transform(X_test)
# Use 20% of samples for validation (0.25 * 0.8 = 0.2) so we end up with 60-20-20 for train/test/validation
X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.25, random_state=SEED)
######
print(X_train.shape)
print(y_train.shape)
# Construct CNN
# init model
model = Sequential()
# add layers
model.add(Conv1D(filters=64, kernel_size=1, activation='relu', input_shape=X_train.shape))
model.add(Conv1D(filters=64, kernel_size=1, activation='relu'))
model.add(Dropout(0.5))
model.add(MaxPooling1D(pool_size=2))
model.add(Flatten())
model.add(Dense(100, activation='relu'))
model.add(Dense(y_train.shape[1], activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) # 'rmsprop'
history = model.fit(X_train, y_train, validation_data=(X_val, y_val), epochs=250, verbose=1)
# print(history)
plt.figure(figsize=(8,10))
plt.subplot(2,1,1)
# summarize history for accuracy
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'validation'], loc='lower right')
plt.subplot(2,1,2)
# summarize history for loss
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'validation'], loc='upper right')
plt.show()
scores = model.evaluate(X_test, y_test)
print(scores)
y_pred = model.predict(X_test)
print(y_pred)
y_pred = np.argmax(y_pred, axis=1)
y_test = np.argmax(y_test, axis=1)
accuracy_score = accuracy_score(y_test, y_pred)
print("Accuracy Score: ", accuracy_score)
confusion_matrix = confusion_matrix(y_test, y_pred)
print(confusion_matrix)
class_report = classification_report(y_test, y_pred, target_names=target_names)
print(class_report)
##
Комментарии:
1. Ошибка, совершенно очевидно
y_train
, имеет одно измерение(89680,)
. В индексе кортежа есть только один элемент0
, но затем вы пытаетесь добавитьy_train.shape[1]
его в свою модель, что, конечно, приведет к ростуindex error
.2. Да, я знал, что это правда, однако решение неясно.
3. Попробуй
model.add(Dense(89680, activation='softmax'))
4. @alec_djinn, который дает
ValueError: Input 0 of layer sequential is incompatible with the layer: expected ndim=3, found ndim=2. Full shape received: [None, 25]
5. Сколько классов содержится в вашем наборе данных? Если существует более 2 классов, то просто нужно обновить model.add(Плотный(y_train.shape[1], активация=’softmax’)). Если есть только два класса, то вам нужно перейти
loss
наbinary_crossentropy
иsoftmax
наsigmoid
. Спасибо