Вопрос или проблема
Для моего итогового проекта я работаю с Keras и пытаюсь создать разные модели ИИ. У меня возникают трудности с многослойным перцептроном (MLP). Сначала я обрабатываю набор данных UNSW-NB15, а затем использую его в нейронной сети. Вот как выглядит предварительная обработка:
import pandas as pd
import numpy as np
from tensorflow.keras.utils import get_file
import numpy as np
import tensorflow.keras
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Activation
from sklearn.model_selection import train_test_split
from tensorflow.keras.callbacks import EarlyStopping
from sklearn import metrics
from sklearn.preprocessing import OrdinalEncoder
dfs = []
for i in range(1,5):
path="./UNSW-NB15_{}.csv" # Существуют 4 входных файла CSV
dfs.append(pd.read_csv(path.format(i),dtype={'attack_cat': str, 'ct_ftp_cmd' : int }, header = None))
all_data = pd.concat(dfs).reset_index(drop=True) # Объединение всех данных в один датафрейм
Этот CSV файл содержит названия всех признаков
df_col = pd.read_csv('./NUSW-NB15_features.csv', encoding='ISO-8859-1')
Приведение названий колонок к нижнему регистру, удаление пробелов
df_col['Name'] = df_col['Name'].apply(lambda x: x.strip().replace(' ', '').lower())
Переименование нашего датафрейма с правильными названиями колонок
all_data.columns = df_col['Name']
all_data.drop(['srcip', 'sport', 'dstip', 'dsport', 'ct_ftp_cmd','state'],axis=1, inplace=True)
all_data['attack_cat'] = all_data['attack_cat'].str.strip()
all_data['attack_cat'] = all_data['attack_cat'].replace(['Backdoors'], 'Backdoor')
all_data.groupby('attack_cat')['attack_cat'].count()
all_data["attack_cat"] = all_data["attack_cat"].fillna('Normal')
all_data.groupby('attack_cat')['attack_cat'].count()
all_data.drop(all_data[all_data['is_ftp_login'] >= 2.0].index, inplace = True)
all_data['ct_flw_http_mthd'] = all_data['ct_flw_http_mthd'].fillna(0)
all_data['is_ftp_login'] = all_data['is_ftp_login'].fillna(0)
ord_enc = OrdinalEncoder()
all_data['encoded'] = ord_enc.fit_transform(all_data[['attack_cat']])
all_data['encoded_int'] = all_data['encoded'].astype(int)
all_data.drop(['encoded'],axis=1)
all_data.drop(['encoded_int'],axis=1)
ord_enc_serv = OrdinalEncoder()
all_data['encoded_serv'] = ord_enc_serv.fit_transform(all_data[['service']])
all_data['int_serv'] = all_data['encoded_serv'].astype(int)
all_data.drop(['encoded_serv'],axis=1)
all_data.drop(['encoded','encoded_serv'],axis=1)
ord_enc_proto = OrdinalEncoder()
all_data['encoded_proto'] = ord_enc.fit_transform(all_data[['proto']])
all_data['int_proto'] = all_data['encoded_proto'].astype(int)
all_data= all_data.drop(['encoded_proto'],axis=1)
encoded_data = all_data.drop(['encoded','encoded_serv','proto','service','attack_cat','label'],axis=1)
multi_data = encoded_data
X = multi_data.drop(columns=['encoded_int'],axis=1)
Y = multi_data['encoded_int']
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X,Y, train_size = 0.8, test_size = 0.2, random_state = 0,stratify = Y)
А это модель:
model = Sequential()
model.add(Dense(X.shape[1], input_dim= X.shape[1], activation= 'relu'))
model.add(Dense(2*X.shape[1]+1, activation= 'relu'))
model.add(Dense(2*X.shape[1]+1,activation= 'relu'))
model.add(Dense(10,activation= 'softmax', kernel_initializer="normal"))
model.compile(loss="sparse_categorical_crossentropy", optimizer="adam", metrics= ['accuracy'])
monitor = EarlyStopping(monitor="val_loss", min_delta=1e-3, patience=5,
verbose=1, mode="auto", restore_best_weights=True)
model.fit(X_train,y_train,validation_data=(X_test,y_test),
callbacks=[monitor],batch_size=10000,verbose=2, epochs=100)
Оценка модели на тестовом наборе
from sklearn.metrics import classification_report
y_pred = model.predict(X_test)
y_pred_classes = y_pred
print(classification_report(y_test, y_pred_classes))
Сейчас ноутбук выдает такую ошибку:
Метрики классификации не могут обрабатывать смешанные целевые переменные и непрерывные многовыводные цели
Мне нужна помощь, так как я сделал несколько версий, но не могу получить правильную. Не знаю, в модели ли проблема или в чем-то другом, но я хотел бы получить оценку точности и метрики, чтобы видеть для каждого класса атаки его значения.
Спасибо за помощь.
Правка:
Наконец я смог заставить это работать. Сейчас получаю значение точности примерно в 71%. Что я сделал, так это выбрал 20 самых важных признаков, а затем нормализовал данные. Я получил эти 71% с функцией активации сигмоид на каждом слое, кроме выходного. Я пробую разные конфигурации и функции активации. Как можно повысить точность?
Строка, в которой вызывается classification_report, выдает ошибку Метрики классификации не могут обрабатывать смешанные целевые переменные и непрерывные многовыводные цели, потому что y_pred_classes — это вывод из softmax, поэтому это будет (507973,10) массив с плавающей запятой, а y_test — это (507973) массив целых чисел — то есть вам нужно преобразовать вывод softmax обратно в категории, чтобы сравнить с вашими истинными метками.
Что-то вроде этого y_preds = np.argmax(y_pred_classes, axis=1)
позволит вызвать classification_report без выброса. Вы также можете добавить названия целей, так что что-то вроде:
target_names=["attack0", "attack1", "attack2", "attack3", "attack4", "attack5", "attack6", "attack7", "attack8", "attack9" ]
y_preds = np.argmax(y_pred_classes, axis=1)
print(classification_report(y_test, y_preds, target_names=target_names))
Я бы рекомендовал взглянуть на матрицу путаницы.
from sklearn.metrics import multilabel_confusion_matrix
multilabel_confusion_matrix(y_test, y_preds)
или
import matplotlib.pyplot as plt
from sklearn.metrics import ConfusionMatrixDisplay
ConfusionMatrixDisplay.from_predictions(y_test, y_preds)
plt.show()
Это покажет вам, что обученный классификатор просто относит все к классу 6. Хорошей отправной точкой будет понимание распределений данных ваших классов. Существует множество подходов для работы с сильно перекошенными входными данными, включая пере- и недовыборку, или взвешивание классов в соответствии с их входными распределениями. Это хороший урок по взвешиванию классов в Keras: https://www.tensorflow.org/tutorials/structured_data/imbalanced_data
.
Ответ или решение
Ваш вопрос о проблеме с MLP (многослойным перцептроном) в Keras при работе с набором данных UNSW-NB15 требует внимательного анализа вашей предварительной обработки данных и структуры модели для улучшения результатов и избежания ошибок.
Понимание проблемы и решение ошибок
Вы столкнулись с ошибкой: "Classification metrics can’t handle a mix of multiclass and continuous-multioutput targets". Это связано с тем, что выход модели после функции softmax
является массивом вероятностей, который необходимо преобразовать в категориальные метки для сравнения с истинными значениями. Вы можете использовать функцию np.argmax
для конвертации:
y_preds = np.argmax(y_pred_classes, axis=1)
После этого вызов classification_report
можно осуществить корректно:
target_names=["attack0", "attack1", "attack2", "attack3", "attack4", "attack5", "attack6", "attack7", "attack8", "attack9"]
print(classification_report(y_test, y_preds, target_names=target_names))
Увеличение точности модели
Теперь, когда вы добились работы модели, стоит рассмотреть несколько стратегий для повышения точности:
-
Анализ и нормализация данных: Используйте только значимые признаки и нормализуйте данные для обеспечения единообразного масштаба. Вы сделали это и повысили точность до 71%. Это хороший старт, но нормализация всех переменных может ещё больше улучшить результаты.
-
Изменение архитектуры сети: Экспериментируйте с числом и размером слоёв. Попробуйте добавлять слои, изменять функцию активации (например,
tanh
илиleaky_relu
) и методы инициализации весов (например,he_normal
). -
Решение проблемы дисбаланса классов: Если ваши данные сильно несбалансированы по классам, подумайте о стратегиях управления несбалансированными данными. Это может включать взвешивание классов при обучении модели, использование методов увеличения или уменьшения выборки. В Keras вы можете использовать параметр
class_weight
в методеfit
. -
Использование регуляризации: Внедрение методов регуляризации, таких как L1 или L2, может помочь предотвратить переобучение.
-
Использование кросс-валидации: Это позволит вам лучше оценить работоспособность модели и выявить наиболее оптимальные гиперпараметры.
Анализ результатов и визуализация
Диагностика модели — это не только анализ метрик, но и визуализация ошибок и успехов. Постройте матрицу ошибок (confusion matrix) для детального понимания того, какие именно классы ваша модель путает:
from sklearn.metrics import ConfusionMatrixDisplay
import matplotlib.pyplot as plt
ConfusionMatrixDisplay.from_predictions(y_test, y_preds)
plt.show()
Заключение
При создании эффективной модели глубинного обучения важно тщательно подходить как к предварительной обработке данных, так и к проектированию и настройке сети. Отшлифовывание этих компонентов поможет вам не только избежать ошибок, но и добиться высоких показателей точности, что важно для успешной реализации проектов в сфере AI.