Классификация изображений является важной задачей компьютерного зрения. Он включает в себя идентификацию содержимого изображения и соответствующую маркировку. В этом посте мы создадим классификатор моды, используя PyTorch и Grid Search. Мы будем использовать набор данных Fashion-MNIST, который содержит 60 000 обучающих изображений и 10 000 тестовых изображений 10 различных типов одежды.
Наша цель — построить нейронную сеть, которая сможет точно классифицировать изображения. Для этого мы будем использовать PyTorch, популярную библиотеку машинного обучения с открытым исходным кодом. Кроме того, мы будем использовать поиск по сетке для настройки гиперпараметров нашей нейронной сети для достижения максимально возможной точности.
Начиная
Во-первых, давайте импортируем необходимые библиотеки:
import torch from torch import nn from torch.utils.data import DataLoader from torchvision import datasets from torchvision.transforms import ToTensor import matplotlib.pyplot as plt import json
Здесь мы импортируем PyTorch вместе с некоторыми другими необходимыми библиотеками, такими как torchvision для загрузки и преобразования данных и matplotlib для визуализации результатов.
Предварительная обработка данных
Прежде чем мы сможем обучить нашу модель, нам нужно предварительно обработать данные. Мы будем использовать набор данных FashionMNIST, который включен в модуль torchvision.datasets. Мы будем использовать преобразование ToTensor() для преобразования данных в тензоры PyTorch и нормализации данных. Кроме того, мы разделим данные на наборы для обучения и тестирования, используя функцию загрузки данных.
# set up a data downloader function
def data_download():
train_data = datasets.FashionMNIST(
root="data",
train=True,
download=True,
transform=ToTensor(),
)
test_data = datasets.FashionMNIST(
root="data",
train=False,
download=True,
transform=ToTensor(),
)
return train_data,test_data
Далее нам нужно создать загрузчики данных для наших данных обучения и тестирования. Загрузчики данных позволяют нам эффективно загружать и предварительно обрабатывать данные партиями во время обучения.
# set up a data loader function
def dataloader(train_data, test_data):
batch_size = 64
train_dataloader = DataLoader(train_data, batch_size=batch_size)
test_dataloader = DataLoader(test_data, batch_size=batch_size)
return train_dataloader, test_dataloader
Архитектура модели
Мы будем использовать полносвязную нейронную сеть с функциями активации ReLU для нашего классификатора. Вход в сеть — это изображение в градациях серого 28x28, которое мы сглаживаем в 784-мерный вектор. Выход сети представляет собой распределение вероятностей по 10 классам.
# we define the model
class ClassifierNetwork(nn.Module):
def __init__(self, hidden_units):
super().__init__()
self.flatten = nn.Flatten()
self.linear_relu_stack = nn.Sequential(
nn.Linear(28*28, hidden_units),
nn.ReLU(),
nn.Linear(hidden_units, hidden_units),
nn.ReLU(),
nn.Linear(hidden_units, 10)
)
def forward(self, x):
x = self.flatten(x)
logits = self.linear_relu_stack(x)
return logits
Обучение и тестирование
Теперь давайте определим наши функции train() и test(). Функция train() выполняет обратное распространение и обновляет параметры нейронной сети. Функция test() оценивает точность модели на тестовых данных.
def train(dataloader, model, device, lr):
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr = lr)
size = len(dataloader.dataset)
model.train()
for batch, (X,y) in enumerate(dataloader):
X, y = X.to(device), y.to(device)
# find loss
y_pred = model(X)
loss = loss_fn(y_pred, y)
# backpropagation
loss.backward()
optimizer.step()
optimizer.zero_grad()
if batch % 100 == 0:
loss, current = loss.item(), (batch + 1) * len(X)
print(f"loss {loss:>7f} [{current:>5d}/{size:>5d}]")
def test(dataloader, model, device):
loss_fn = nn.CrossEntropyLoss()
size = len(dataloader.dataset)
num_batches = len(dataloader)
model.eval()
test_loss, correct = 0, 0
with torch.no_grad():
for X, y in dataloader:
X, y = X.to(device), y.to(device)
y_pred = model(X)
test_loss += loss_fn(y_pred, y).item()
correct += (y_pred.argmax(1) == y).type(torch.float).sum().item()
test_loss /= num_batches
correct /= size
accuracy = 100*correct
print(f"Test Error: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")
return accuracy
Функция test() принимает на вход загрузчик данных, модель и устройство. Затем он оценивает точность модели на тестовых данных. Сначала мы устанавливаем модель в режим оценки, используя model.eval(). Это отключает отсев и нормализацию пакетов, которые обычно используются во время обучения, но не во время тестирования.
Затем мы перебираем тестовые данные партиями и вычисляем потери и точность модели. Мы используем функцию потерь nn.CrossEntropyLoss(), которая подходит для задач классификации с несколькими классами, таких как наша. Мы также рассчитываем точность модели, сравнивая предсказанные метки классов с метками истинности.
Поиск по сетке
Далее мы будем использовать поиск по сетке для настройки гиперпараметров нашей нейронной сети. Мы будем искать по ряду скрытых единиц и темпов обучения. Мы определяем функцию grid_search(), которая принимает список скрытых единиц, список скоростей обучения и устройство в качестве входных данных.
def grid_search(hidden_units_list, learning_rates, device):
best_accuracy = 0
best_lr = None
best_hidden_units = None
for lr in learning_rates:
for hidden_units in hidden_units_list:
print(f"Performing a Training with Grid Search using learning rate {lr} and {hidden_units} hidden_units\n")
Model = ClassifierNetwork(hidden_units).to(device)
train_data, test_data = data_download()
train_dataloader, test_dataloader = dataloader(train_data, test_data)
epochs = 5
for t in range(epochs):
print(f"Epoch {t+1}\n---------------------------")
train(train_dataloader,Model,device,lr)
test_accuracy = test(test_dataloader,Model,device)
if test_accuracy > best_accuracy:
best_accuracy = test_accuracy
best_lr = lr
best_hidden_units = hidden_units
return best_lr, best_hidden_units, best_accuracy
Здесь мы перебираем каждую комбинацию гиперпараметров и обучаем модель в течение 5 эпох, используя функции train() и test(). Затем мы проверяем, лучше ли точность модели, чем текущая наилучшая точность. Если это так, мы обновляем лучшую точность, лучшую скорость обучения и лучшее количество скрытых единиц.
Наконец, мы возвращаем лучшие гиперпараметры, которые затем можем использовать для обучения модели в течение более длительного периода.
Запуск кода
Чтобы запустить код, мы можем вызвать функцию main():
def main():
device = "cpu"
print(f"Using {device} device")
learning_rates = [0.1,0.2,0.3]
hidden_units_list = [128,256,512,1024]
train_data, test_data = data_download()
train_dataloader, test_dataloader = dataloader(train_data, test_data)
user_input = input("Do you want to train the model? (yes/no): ")
if user_input.lower() == 'yes':
best_lr, best_hidden_units, best_accuracy = grid_search(hidden_units_list, learning_rates, device)
train_best_model(train_dataloader, test_dataloader, best_lr, best_hidden_units, device)
else:
Model = ClassifierNetwork(best_hidden_units).to(device)
Model.load_state_dict(torch.load("model_best.pth"))
Model.eval()
print("Loaded saved model.")
Здесь мы сначала устанавливаем устройство на «процессор». Затем мы определяем списки скоростей обучения и скрытых единиц, загружаем данные и создаем загрузчики данных.
Затем мы предлагаем пользователю ввести, хотят ли они обучить модель или загрузить сохраненную модель. Если пользователь хочет обучить модель, мы вызываем функцию grid_search(), чтобы найти лучшие гиперпараметры, а затем обучаем лучшую модель с помощью функции train_best_model(). Если пользователь хочет загрузить сохраненную модель, мы загружаем сохраненную модель с помощью torch.load() и устанавливаем модель в режим оценки с помощью model.eval().
Развертывание вашей модели машинного обучения в облаке
Введение в развертывание
В этом разделе мы покажем вам, как развернуть вашу модель машинного обучения, такую как Fashion Classifier, в облаке. Мы будем использовать Flask, облегченную веб-инфраструктуру, для создания веб-приложения и Heroku, облачную платформу, для развертывания.
Шаг 1: Настройте каталог вашего проекта
Создайте новый каталог для вашего проекта и настройте следующую структуру:
your_project/ | |-- app.py |-- requirements.txt |-- Procfile |-- model/ | |-- model.py | |-- model.pkl |-- templates/ | |-- index.html | |-- result.html
Шаг 2: Установите Фласк
Если вы еще этого не сделали, установите Flask с помощью следующей команды:
pip install Flask
Шаг 3: Создайте свое веб-приложение
В app.py создайте простое веб-приложение Flask для обработки пользовательского ввода и отображения результатов:
from flask import Flask, render_template, request
import model.model as model
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
user_input = request.form['user_input']
prediction = model.predict(user_input)
return render_template('result.html', prediction=prediction)
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True)
Шаг 4: Создайте HTML-шаблоны
Создайте два HTML-шаблона в папке templates: index.html для пользовательского ввода и result.html для отображения результатов.
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Your Model</title>
</head>
<body>
<h1>Your Model</h1>
<form action="/" method="POST">
<label for="user_input">Enter your input:</label>
<input type="text" name="user_input" id="user_input" required>
<button type="submit">Predict</button>
</form>
</body>
</html>
result.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Your Model</title>
</head>
<body>
<h1>Your Model</h1>
<p>Prediction: {{ prediction }}</p>
<a href="/">Try again</a>
</body>
</html>
Шаг 5: Сохраните и загрузите свою модель
В папке model создайте файл model.py, содержащий функции для сохранения и загрузки обученной модели машинного обучения. Сохраните обученную модель в виде файла .pkl в той же папке:
import pickle
def save_model(model, filename):
with open(filename, 'wb') as file:
pickle.dump(model, file)
def load_model(filename):
with open(filename, 'rb') as file:
return pickle.load(file)
def predict(user_input):
model = load_model('model.pkl')
# Preprocess the user input and make predictions using your model
# The preprocessing and prediction code will vary depending on your model (ARIMA or Naive Bayes)
# For example:
# processed_input = preprocess(user_input)
# prediction = model.predict(processed_input)
# Add the appropriate code for your specific model and return the prediction
return prediction
Шаг 6: Создайте требования и Procfile
Создайте файл `requirements.txt` со следующими библиотеками:
Flask gunicorn numpy pandas matplotlib statsmodels scikit-learn yfinance
Убедитесь, что вы включили все дополнительные библиотеки, которые вы использовали в своем конкретном проекте.
Создайте Procfile со следующим содержимым:
web: gunicorn app:app
Имея эти файлы, вы готовы развернуть свое приложение на Heroku.
Шаг 7. Разверните приложение на Heroku
Сначала установите интерфейс командной строки Heroku и создайте учетную запись на Heroku.
Инициализируйте репозиторий Git в каталоге вашего проекта и зафиксируйте изменения:
git init git add . git commit -m "Initial commit"
Войдите в Heroku и создайте новое приложение Heroku:
heroku login heroku create your-app-name
Разверните приложение:
git push heroku master
Ваша модель машинного обучения теперь развернута на Heroku! Посетите https://your-app-name.herokuapp.com, чтобы просмотреть свое веб-приложение.
Заключение
В этом посте мы создали классификатор моды, используя PyTorch и Grid Search. Мы использовали PyTorch для определения архитектуры нашей нейронной сети и использовали поиск по сетке для настройки гиперпараметров сети. Затем мы обучили сеть, используя лучшие гиперпараметры, и сохранили модель на диск. Наконец, мы показали, как загрузить сохраненную модель и использовать ее для классификации новых изображений.
Используя Grid Search, мы смогли найти лучшие гиперпараметры для нашей сети, что позволило нам достичь более высокой точности, чем мы могли бы достичь с гиперпараметрами по умолчанию.