104 KiB
Лабораторная 12¶
Классификация набора изображений
Датасет: Vehicle Type Recognition (https://www.kaggle.com/datasets/kaggleashwin/vehicle-type-recognition)
import os
os.environ["KERAS_BACKEND"] = "jax"
from keras import backend as K
K.clear_session()
dataset_path = "static/Dataset"
classes = os.listdir(dataset_path)
num_classes = len(classes)
print(f"Всего классов: {num_classes}")
print("Список классов:", classes)
Предобработка изображений и разделение их на выборки
import numpy as np
from sklearn.model_selection import train_test_split
from keras.api.utils import to_categorical
from PIL import Image
img_width, img_height = 224, 224
input_shape = (img_width, img_height, 3)
X = []
y = []
for i, image_class in enumerate(classes):
class_dir = os.path.join(dataset_path, image_class)
for img_file in os.listdir(class_dir):
try:
img_path = os.path.join(class_dir, img_file)
img = Image.open(img_path).convert('RGB')
img = img.resize((img_width, img_height))
img_array = np.array(img) / 255.0
X.append(img_array)
y.append(i)
except Exception as e:
print(f"Ошибка при загрузке {img_path}: {e}")
X = np.array(X)
y = np.array(y)
y = to_categorical(y, num_classes=num_classes)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
print(f"Размер обучающей выборки: {X_train.shape}")
print(f"Размер тестовой выборки: {X_test.shape}")
print(f"Количество классов: {num_classes}")
Проектированию глубокой сверточной нейронной сети
используем AlexNet
from keras.api.models import Sequential
from keras.api.layers import InputLayer, Conv2D, MaxPooling2D, Dropout, Flatten, Dense, BatchNormalization
alexnet_model = Sequential()
alexnet_model.add(InputLayer(shape=(224, 224, 3)))
alexnet_model.add(Conv2D(96, kernel_size=(11, 11), strides=(4, 4), activation="relu"))
alexnet_model.add(MaxPooling2D(pool_size=(3, 3), strides=(2, 2)))
alexnet_model.add(BatchNormalization())
alexnet_model.add(Conv2D(256, kernel_size=(5, 5), activation="relu"))
alexnet_model.add(MaxPooling2D(pool_size=(3, 3), strides=(2, 2)))
alexnet_model.add(BatchNormalization())
alexnet_model.add(Conv2D(256, kernel_size=(3, 3), activation="relu"))
alexnet_model.add(Conv2D(384, kernel_size=(3, 3), activation="relu"))
alexnet_model.add(Conv2D(384, kernel_size=(3, 3), activation="relu"))
alexnet_model.add(MaxPooling2D(pool_size=(3, 3), strides=(2, 2)))
alexnet_model.add(BatchNormalization())
alexnet_model.add(Flatten())
alexnet_model.add(Dense(4096, activation="tanh"))
alexnet_model.add(Dropout(0.5))
alexnet_model.add(Dense(4096, activation="tanh"))
alexnet_model.add(Dropout(0.5))
alexnet_model.add(Dense(num_classes, activation="softmax"))
alexnet_model.summary()
Обучение модели
from keras.api.callbacks import EarlyStopping
alexnet_model.compile(
loss="categorical_crossentropy",
optimizer="adam",
metrics=["accuracy"]
)
early_stop = EarlyStopping(monitor='val_accuracy', patience=10, restore_best_weights=True)
alexnet_model.fit(
x=X_train,
y=y_train,
epochs=100,
validation_data=(X_test, y_test),
callbacks=[early_stop]
)
Оценка качества
def evaluate_model(model, X_test, y_test):
loss, accuracy = model.evaluate(X_test, y_test)
print(f"Loss на тестовой выборке: {loss:.4f}")
print(f"Accuracy на тестовой выборке: {accuracy:.4f}")
evaluate_model(alexnet_model, X_test, y_test)
Качество модели - 41.25% это хуже чем в 9 ЛР, но лучше чем в 11 ЛР
Классификация текстов
import spacy
sp = spacy.load("ru_core_news_lg")
Загрузка текстов из файлов в датафрейм
import pandas as pd
from docx import Document
def read_docx(file_path):
doc = Document(file_path)
full_text = []
for paragraph in doc.paragraphs:
full_text.append(paragraph.text)
return "\n".join(full_text)
def load_docs(dataset_path):
df = pd.DataFrame(columns=["doc", "text"])
for file_path in os.listdir(dataset_path):
if file_path.startswith("~$"):
continue
text = read_docx(dataset_path + file_path)
df.loc[len(df.index)] = [file_path, text]
return df
df = load_docs("static/text/")
df["type"] = df.apply(lambda row: 0 if str(row["doc"]).startswith("tz_") else 1, axis=1)
df.sort_values(by=["doc"], inplace=True)
display(df.head(), df.tail())
Предобработка текста
from gensim.models.phrases import Phraser, Phrases
def prep_text(text):
doc = sp(text)
lower_sents = []
for sent in doc.sents:
lower_sents.append([word.lemma_.lower() for word in sent if not word.is_punct and not word.is_stop and not word.is_space])
lower_bigram = Phraser(Phrases(lower_sents))
clean_sents = []
for sent in lower_sents:
clean_sents.append(lower_bigram[sent])
return clean_sents
df["prep_text"] = df.apply(lambda row: prep_text(row["text"]), axis=1)
display(df.head(), df.tail())
Векторизация текстовых данных
from gensim.models.word2vec import Word2Vec
word2vec = Word2Vec(
sentences=df["prep_text"].explode().tolist(),
vector_size=64,
sg=1,
window=10,
epochs=5,
min_count=10,
workers=4,
seed=9,
)
word_to_id = word2vec.wv.key_to_index
word_to_id = {'pad': 0, **{k: v+1 for k, v in word2vec.wv.key_to_index.items()}}
list(word_to_id.items())[:20]
Преобразуем тексты в списки индексов
def text_to_ids(sentences, word_to_id):
flat_words = [word for sent in sentences for word in sent]
return [word_to_id.get(word, 0) for word in flat_words]
df["ids"] = df["prep_text"].apply(lambda doc: text_to_ids(doc, word_to_id))
padding и truncating
from keras.api.preprocessing.sequence import pad_sequences
max_length = 1500
X = pad_sequences(df["ids"].tolist(), maxlen=max_length, padding="pre", truncating="pre", value=0)
Тренировочная и тестовая выборки
from sklearn.model_selection import train_test_split
y = df["type"].values
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
X_train
y_train
Архитектура глубокой полносвязанной сети
from keras.api.layers import Embedding
vocab_size = len(word_to_id)
model = Sequential()
model.add(InputLayer(shape=(max_length,), dtype="int32"))
model.add(Embedding(input_dim=vocab_size, output_dim=64))
model.add(Flatten())
model.add(Dense(64, activation="relu"))
model.add(Dropout(0.5))
model.add(Dense(1, activation="sigmoid"))
model.summary()
Обучение модели
model.compile(
loss="binary_crossentropy",
optimizer="adam",
metrics=["accuracy"],
)
model.fit(
X_train,
y_train,
batch_size=128,
epochs=5,
validation_data=(X_test, y_test)
)
Оценка качества
evaluate_model(model, X_test, y_test)
Сверточная сеть
from keras.api.layers import SpatialDropout1D, Conv1D, GlobalMaxPooling1D
conv_model = Sequential()
conv_model.add(InputLayer(shape=(max_length,), dtype="int32"))
conv_model.add(Embedding(input_dim=vocab_size, output_dim=64))
conv_model.add(SpatialDropout1D(0.2))
conv_model.add(Conv1D(filters=256, kernel_size=3, activation="relu"))
conv_model.add(GlobalMaxPooling1D())
conv_model.add(Dense(256, activation="relu"))
conv_model.add(Dropout(0.3))
conv_model.add(Dense(1, activation="sigmoid"))
conv_model.summary()
Обучение модели
conv_model.compile(
loss="binary_crossentropy",
optimizer="adam",
metrics=["accuracy"],
)
conv_model.fit(
X_train,
y_train,
batch_size=128,
epochs=5,
validation_data=(X_test, y_test)
)
Оценка качества
evaluate_model(conv_model, X_test, y_test)
Рекуррентная сеть
from keras.api.layers import SimpleRNN
rnn_model = Sequential()
rnn_model.add(InputLayer(shape=(max_length,), dtype="int32"))
rnn_model.add(Embedding(input_dim=vocab_size, output_dim=64))
rnn_model.add(SpatialDropout1D(0.2))
rnn_model.add(SimpleRNN(128, dropout=0.2, recurrent_dropout=0.2))
rnn_model.add(Dense(1, activation="sigmoid"))
rnn_model.summary()
Обучение модели
rnn_model.compile(
loss="binary_crossentropy",
optimizer="adam",
metrics=["accuracy"],
)
early_stop = EarlyStopping(monitor='val_accuracy', patience=10, restore_best_weights=True)
rnn_model.fit(
X_train,
y_train,
batch_size=128,
epochs=40,
validation_data=(X_test, y_test),
callbacks=[early_stop]
)
Оценка качества
evaluate_model(rnn_model, X_test, y_test)
Лучший результат - полносвязанная сеть - 77,78%
Сверточная сеть - 66,78%
Рекуррентная сеть - 60,25%