
Полная версия
Алгоритмы машинного обучения: базовый курс
5. Повторение: Агент повторяет процесс, взаимодействуя с окружающей средой, обновляя Q-таблицу, пока не достигнет цели или не выполнит достаточное количество шагов.
В результате обучения, когда агент выполнит достаточно шагов, его стратегия будет ориентирована на выбор оптимальных действий для достижения цели, избегая столкновений со стенами.
Пример кода Q-Learning для задачи CartPole
Давайте возьмём другую задачу для применения алгоритма Q-learning. Рассмотрим задачу Maze Navigation (навигация по лабиринту), где агент должен найти выход из лабиринта, начиная с одной клетки. Лабиринт состоит из клеток, и агент может двигаться вверх, вниз, влево или вправо. Задача будет заключаться в том, чтобы агент научился искать оптимальный путь к выходу, используя награды за правильные действия и штрафы за неправильные.
Описание задачи:
– Агент начинает в случайной точке лабиринта.
– Он должен найти путь к выходу, избегая стен.
– Если агент сталкивается со стеной, он получает отрицательную награду.
– Если агент достиг цели (выхода), он получает положительную награду.
Мы будем использовать Q-learning для обучения агента, где Q-значения будут обновляться в процессе взаимодействия агента с лабиринтом.
Пример кода для задачи навигации по лабиринту с использованием Q-Learning:
```python
import numpy as np
import random
# Параметры лабиринта
maze = [
[0, 0, 0, 0, 0],
[0, 1, 1, 0, 0],
[0, 0, 0, 1, 0],
[0, 1, 0, 0, 0],
[0, 0, 0, 1, 2]
]
# 0 – свободная клетка
# 1 – стена
# 2 – выход
# Размеры лабиринта
n_rows = len(maze)
n_cols = len(maze[0])
# Гиперпараметры Q-learning
learning_rate = 0.1 # Скорость обучения
discount_factor = 0.9 # Дисконтирование
epsilon = 0.2 # Эпсилон для epsilon-greedy
num_episodes = 1000 # Количество эпизодов обучения
# Инициализация Q-таблицы
q_table = np.zeros((n_rows, n_cols, 4)) # 4 действия: вверх, вниз, влево, вправо
actions = [(-1, 0), (1, 0), (0, -1), (0, 1)] # Действия: (изменение по строкам, изменение по столбцам)
# Функция выбора действия с использованием epsilon-greedy
def epsilon_greedy(state):
if random.uniform(0, 1) < epsilon:
return random.choice([0, 1, 2, 3]) # Случайное действие
else:
return np.argmax(q_table[state[0], state[1]]) # Лучшее действие по Q-таблице
# Функция проверки, находится ли клетка внутри лабиринта и является ли она свободной
def is_valid_move(state, action):
new_row = state[0] + actions[action][0]
new_col = state[1] + actions[action][1]
if 0 <= new_row < n_rows and 0 <= new_col < n_cols and maze[new_row][new_col] != 1:
return True
return False
# Обучение
for episode in range(num_episodes):
state = (0, 0) # Начальное состояние (агент стартует в верхнем левом углу)
done = False
total_reward = 0
while not done:
action = epsilon_greedy(state) # Выбор действия
if is_valid_move(state, action):
next_state = (state[0] + actions[action][0], state[1] + actions[action][1])
else:
next_state = state # Если движение невозможно, остаемся на месте
# Получение награды
if maze[next_state[0]][next_state[1]] == 2:
reward = 100 # Если агент достиг выхода, награда
done = True
elif maze[next_state[0]][next_state[1]] == 1:
reward = -10 # Если агент столкнулся со стеной, штраф
else:
reward = -1 # Пустая клетка, небольшая отрицательная награда для побуждения к поиску выхода
# Обновление Q-таблицы
q_table[state[0], state[1], action] = q_table[state[0], state[1], action] + learning_rate * (
reward + discount_factor * np.max(q_table[next_state[0], next_state[1]]) – q_table[state[0], state[1], action]
)
state = next_state # Переход к следующему состоянию
total_reward += reward
if episode % 100 == 0:
print(f"Episode {episode}/{num_episodes}, Total Reward: {total_reward}")
# Тестирование обученной модели
state = (0, 0)
done = False
total_reward = 0
steps = []
while not done:
action = np.argmax(q_table[state[0], state[1]]) # Лучшее действие по Q-таблице
if is_valid_move(state, action):
next_state = (state[0] + actions[action][0], state[1] + actions[action][1])
else:
next_state = state
# Получение награды
if maze[next_state[0]][next_state[1]] == 2:
reward = 100
done = True
elif maze[next_state[0]][next_state[1]] == 1:
reward = -10
else:
reward = -1
state = next_state
total_reward += reward
steps.append(state)
print(f"Test Total Reward: {total_reward}")
print("Optimal path to the exit:")
print(steps)
```
Объяснение шагов кода:
1. Определение лабиринта: Лабиринт задан двумерным массивом, где 0 – это свободная клетка, 1 – стена, а 2 – выход. Агент должен найти путь из верхнего левого угла к выходу, избегая стен.
2. Инициализация Q-таблицы: Мы создаём Q-таблицу размером ( n_{text{rows}} times n_{text{cols}} times 4 ), где 4 – это количество возможных действий (вверх, вниз, влево, вправо).
3. epsilon-greedy стратегия: Агент выбирает действие с использованием ε-стратегии. С вероятностью ε агент выбирает случайное действие (для исследования), а с вероятностью 1 – ε выбирает наилучшее действие (по текущим значениям в Q-таблице).
4. Обновление Q-таблицы: После выполнения действия агент получает награду. Если он дошёл до выхода, он получает большую положительную награду. Если он столкнулся с стеной, то получит штраф. Для других клеток даётся небольшая отрицательная награда, чтобы побудить агента искать выход. Q-таблица обновляется с учётом полученной награды и наилучшей стратегии для следующего состояния.
5. Тестирование: После обучения агент проходит через лабиринт, следуя оптимальной стратегии, которая была извлечена из обученной Q-таблицы.
Результаты
После обучения агент будет способен пройти лабиринт, следуя оптимальному пути, избегая стен и минимизируя количество шагов до выхода.
Q-learning – это метод, который позволяет агентам учиться принимать оптимальные решения в различных средах, используя опыт. Он подходит для множества задач, начиная от игр и робототехники и заканчивая оптимизацией бизнес-процессов и управления.
Полусупервизорные подходы
Полусупервизорное обучение – это метод машинного обучения, который сочетает в себе как размеченные, так и неразмеченные данные. В отличие от традиционного супервизорного обучения, где все данные имеют метки (цели), и несупервизорного обучения, где метки отсутствуют, полусупервизорное обучение позволяет использовать как небольшую часть размеченных данных, так и большое количество неразмеченных. Этот подход особенно полезен, когда получение меток для данных является дорогим или трудоемким процессом, а неразмеченные данные доступны в большом объеме.
Основные идеи полусупервизорного обучения
Полусупервизорное обучение может быть особенно эффективным в реальных задачах, где большая часть данных не имеет меток, а аннотирование данных требует значительных затрат времени или усилий. Например, в задачах распознавания изображений, где требуется аннотировать каждое изображение, а данных для обучения очень много, может быть полезно использование большого количества неразмеченных данных вместе с небольшой частью размеченных.
Одним из основных принципов полусупервизорного обучения является использование структурной информации, которая может быть извлечена из неразмеченных данных, чтобы помочь в обучении модели. Например, если модель знает, что объекты, которые близки друг к другу по характеристикам (например, по изображениям или тексту), скорее всего, будут иметь схожие метки, она может использовать эту информацию для повышения точности предсказаний, даже если точных меток мало.
Применение полусупервизорных методов
1. Классификация изображений: В области компьютерного зрения полусупервизорные методы широко применяются для задач классификации, где имеются тысячи или миллионы изображений, но только малая часть из них аннотирована. Например, можно использовать неразмеченные изображения для улучшения классификации животных или объектов, добавляя структуру в обучающий процесс.
2. Обработка текстов: В обработке естественного языка полусупервизорное обучение может быть использовано для улучшения моделей перевода текста или анализа настроений, где аннотированные данные (например, с метками положительного или отрицательного настроя) ограничены.
3. Обработка биологических данных: В биоинформатике, например, для анализа генетических данных, получение меток может быть дорогим, но большие объемы неразмеченных данных могут быть использованы для обучения моделей, например, для предсказания структур белков или поиска новых биологических закономерностей.
Подходы в полусупервизорном обучении
1. Методы на основе графов: В этих методах данные представляются в виде графа, где вершины графа – это данные, а рёбра – это связи между ними. При этом связи могут быть как между размеченными, так и между неразмеченными примерами. Модели, работающие с графами, пытаются минимизировать функции потерь с учётом как размеченных, так и неразмеченных данных. Такие методы полезны, например, для сегментации изображений или для обучения на текстах.
2. Методы самонаблюдения: Самонаблюдение – это подход, при котором модель обучается не только на метках, но и на структуре самих данных. Например, можно применять самообучающиеся алгоритмы, которые используют автоматическое помечание неразмеченных данных с помощью модели, а затем с использованием этих "прогнозированных" меток дообучают модель. Например, модель, которая учит себя классифицировать текстовые фрагменты, генерируя свои собственные метки.
3. Методы на основе обучения с регуляциями: В таких подходах для использования неразмеченных данных применяются методы, которые вводят дополнительные ограничения или регуляризаторы, чтобы гарантировать, что полученные гипотезы на основе размеченных и неразмеченных данных являются согласованными. Например, модель может быть обучена на размеченных данных с добавлением регуляризаторов, чтобы она лучше обобщалась на неразмеченные данные, поддерживая определенную структурную целостность.
4. Генеративные модели: Генеративные модели, такие как вариационные автоэнкодеры (VAE) или генеративные состязательные сети (GAN), могут использоваться для полусупервизорного обучения, позволяя моделям изучать скрытую структуру в данных. Генеративные подходы могут создать обучающие примеры, которые затем используются для обучения классификаторов.
Пример: Полусупервизорное обучение с использованием метода обучения с самонаблюдением
Для примера возьмем задачу классификации текста, где у нас есть большое количество неразмеченных текстов, а метки есть только для небольшой части. Мы можем использовать модель самообучения, которая будет обучаться на небольшом наборе размеченных данных, а затем применить её для прогнозирования меток для неразмеченных текстов, которые затем добавляются в обучающий процесс.
Пример простого кода для этой задачи:
```python
import numpy as np
from sklearn.datasets import fetch_20newsgroups
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction.text import CountVectorizer
# Загрузка данных
newsgroups = fetch_20newsgroups(subset='all')
X = newsgroups.data
y = newsgroups.target
# Разделение данных на размеченные и неразмеченные
X_train, X_unlabeled, y_train, _ = train_test_split(X, y, test_size=0.9, random_state=42)
# Преобразование текста в числовые признаки
vectorizer = CountVectorizer(stop_words='english')
X_train_vec = vectorizer.fit_transform(X_train)
X_unlabeled_vec = vectorizer.transform(X_unlabeled)
# Инициализация модели
model = MultinomialNB()
# Обучение модели на размеченных данных
model.fit(X_train_vec, y_train)
# Прогнозирование для неразмеченных данных
pseudo_labels = model.predict(X_unlabeled_vec)
# Добавление неразмеченных данных с прогнозированными метками в обучающий набор
X_train_combined = np.vstack([X_train_vec.toarray(), X_unlabeled_vec.toarray()])
y_train_combined = np.hstack([y_train, pseudo_labels])
# Дополнительное обучение модели с расширенным набором данных
model.fit(X_train_combined, y_train_combined)
# Оценка качества
accuracy = model.score(X_train_combined, y_train_combined)
print(f'Accuracy: {accuracy:.4f}')
```
Объяснение кода:
1. Загрузка данных: Мы используем набор данных 20 Newsgroups, который содержит текстовые данные, относящиеся к различным новостным группам.
2. Разделение на размеченные и неразмеченные данные: Мы разделяем данные на размеченные (10%) и неразмеченные (90%) данные.
3. Прогнозирование меток для неразмеченных данных: Сначала мы обучаем модель на размеченных данных и используем её для предсказания меток для неразмеченных данных (псевдонаметки).
4. Перенос обучения на расширенный набор: Модель дообучается, используя данные с псевдонаметками, что помогает улучшить её обобщающие способности.
Полусупервизорное обучение представляет собой инструмент, который позволяет эффективно использовать как размеченные, так и неразмеченные данные, что особенно полезно в условиях ограниченности размеченных данных. Существуют различные подходы к полусупервизорному обучению, включая методы графов, самонаблюдения и генеративные модели, которые могут применяться в разных областях, таких как обработка текстов, изображений и биологических данных.
Глава 7. Линейные модели
– Линейная и логистическая регрессия
– Регуляризация: Ridge и Lasso
– Проблемы переобучения
Линейные модели занимают центральное место в машинном обучении, поскольку они являются одними из самых простых и интерпретируемых методов анализа данных. Несмотря на свою кажущуюся простоту, эти модели обладают высокой эффективностью и широко применяются в задачах прогнозирования, классификации и анализа взаимосвязей между переменными.
Основной идеей линейных моделей является представление зависимости между входными признаками и целевой переменной в виде линейной комбинации. Это позволяет быстро обучать модели, легко интерпретировать полученные коэффициенты и эффективно решать задачи с большим числом наблюдений. Однако линейные модели подвержены ряду проблем, таких как переобучение и чувствительность к выбросам, что требует применения специальных методов регуляризации и оценки их качества.
В этой главе мы рассмотрим две ключевые линейные модели: линейную регрессию, используемую для предсказания числовых значений, и логистическую регрессию, которая применяется в задачах классификации. Также разберем методы регуляризации, такие как Ridge и Lasso, которые помогают предотвратить переобучение, улучшая обобщающую способность модели. В завершение обсудим основные причины переобучения линейных моделей и способы их устранения, чтобы добиться наилучших результатов при работе с реальными данными.
Линейная и логистическая регрессия
Линейная регрессия – один из самых простых и интуитивно понятных методов прогнозирования. Её суть заключается в том, что зависимость между входными переменными и выходной переменной представляется в виде линейной функции. Например, если нужно предсказать стоимость квартиры, то учитываются такие факторы, как её площадь, количество комнат и район, а модель пытается найти такие коэффициенты, которые позволят наиболее точно восстановить зависимость между этими параметрами и ценой.
Линейная регрессия обучается на основе имеющихся данных, подбирая такие значения коэффициентов, чтобы разница между реальными и предсказанными значениями была минимальной. После того как модель обучена, её можно использовать для предсказания новых значений на основе аналогичных входных данных. Этот метод особенно полезен, когда зависимость между переменными действительно близка к линейной, однако в реальной жизни данные часто содержат шум, выбросы или нелинейные зависимости, что может затруднить получение точных предсказаний.
В отличие от линейной регрессии, которая применяется для предсказания числовых значений, логистическая регрессия используется для задач классификации, где требуется определить, к какому классу относится объект. Например, если нужно предсказать, купит ли пользователь товар в интернет-магазине, то модель принимает во внимание такие параметры, как частота посещений сайта, средний чек предыдущих покупок и время, проведённое на странице товара. Вместо предсказания конкретного числа, как в линейной регрессии, логистическая регрессия выдаёт вероятность того, что объект принадлежит к определённому классу.
Основная особенность логистической регрессии заключается в том, что выходные значения ограничены диапазоном от 0 до 1, что делает этот метод особенно удобным для задач бинарной классификации. Например, в задаче медицинской диагностики модель может предсказывать вероятность наличия заболевания у пациента на основе его симптомов и анализов. Если вероятность выше определённого порога, пациента относят к группе с повышенным риском, если ниже – к здоровой группе.
Хотя логистическая регрессия является инструментом для классификации, она лучше всего работает в случаях, когда классы хорошо разделимы с помощью линейной границы. Если данные имеют сложную структуру или включают сильно пересекающиеся группы, точность модели может снижаться. В таких случаях могут потребоваться более сложные методы, такие как нейросети или градиентный бустинг, но логистическая регрессия остаётся хорошей отправной точкой, благодаря своей интерпретируемости и эффективности на больших наборах данных.
Линейная и логистическая регрессия – это универсальные инструменты, которые можно применять в самых разных задачах: от предсказания продаж в бизнесе до медицинской диагностики и анализа пользовательского поведения. Их простота, скорость обучения и интерпретируемость делают их важной частью арсенала аналитиков данных и специалистов по машинному обучению.
Примеры использования линейной и логистической регрессии
Разберем два примера: первый – применение линейной регрессии для предсказания стоимости квартиры, второй – использование логистической регрессии для классификации пассажиров «Титаника» на выживших и погибших.
Пример 1: Линейная регрессия для предсказания стоимости квартиры
Допустим, у нас есть данные о квартирах, включая площадь, количество комнат и удаленность от центра города. Наша цель – предсказать стоимость квартиры на основе этих параметров.
Шаг 1: Загрузка данных и подготовка
Сначала установим необходимые библиотеки и загрузим данные.
```python
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error, mean_squared_error
# Создадим искусственный набор данных
data = {
'Площадь': [30, 45, 50, 60, 75, 90, 110, 150, 200, 250],
'Комнат': [1, 1, 2, 2, 3, 3, 4, 5, 6, 7],
'Удаленность_от_центра': [10, 8, 7, 5, 4, 3, 2, 1, 1, 1],
'Цена': [3.5, 5.0, 6.0, 7.5, 9.0, 11.0, 13.5, 18.0, 24.0, 30.0]
}
df = pd.DataFrame(data)
# Разделим данные на входные признаки (X) и целевую переменную (y)
X = df[['Площадь', 'Комнат', 'Удаленность_от_центра']]
y = df['Цена']
# Разделим выборку на обучающую и тестовую
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
```
Шаг 2: Обучение модели линейной регрессии
Создадим и обучим модель.
```python
# Создаем модель линейной регрессии
model = LinearRegression()
# Обучаем модель
model.fit(X_train, y_train)
# Предсказываем цены квартир на тестовых данных
y_pred = model.predict(X_test)
```
Шаг 3: Оценка качества модели
Оценим точность предсказаний, используя метрики MSE и MAE.
```python
mse = mean_squared_error(y_test, y_pred)
mae = mean_absolute_error(y_test, y_pred)
print(f"Среднеквадратичная ошибка (MSE): {mse:.2f}")
print(f"Средняя абсолютная ошибка (MAE): {mae:.2f}")
```
Шаг 4: Визуализация результатов
Посмотрим, насколько предсказанные значения соответствуют реальным.
```python
plt.scatter(y_test, y_pred)
plt.xlabel("Фактическая цена (млн)")
plt.ylabel("Предсказанная цена (млн)")
plt.title("Сравнение предсказанных и реальных цен")
plt.show()
```
Вывод: если модель обучилась хорошо, точки на графике будут близки к диагональной линии, что указывает на точность предсказаний.
Пример 2: Логистическая регрессия для предсказания выживания на «Титанике»
Теперь рассмотрим задачу бинарной классификации. Используем логистическую регрессию, чтобы предсказать, выживет ли пассажир, основываясь на его возрасте, классе каюты и количестве родственников на борту.
Шаг 1: Загрузка и подготовка данных
Загрузим и обработаем известный набор данных Titanic.
```python
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score, classification_report
import seaborn as sns
# Загружаем данные Titanic
url = "https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv"
df = pd.read_csv(url)
# Оставляем только нужные колонки
df = df[['Survived', 'Pclass', 'Age', 'SibSp', 'Parch']]
# Удаляем строки с пропущенными значениями
df.dropna(inplace=True)
# Разделяем на признаки и целевую переменную
X = df[['Pclass', 'Age', 'SibSp', 'Parch']]
y = df['Survived']
# Стандартизация данных для улучшения качества модели
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# Разбиваем на обучающую и тестовую выборки
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)
```
Шаг 2: Обучение модели логистической регрессии
Создадим и обучим модель.
```python
# Создаем модель логистической регрессии
log_model = LogisticRegression()
# Обучаем модель
log_model.fit(X_train, y_train)
# Предсказываем выживаемость пассажиров
y_pred = log_model.predict(X_test)
```
Шаг 3: Оценка качества модели
Выведем метрики точности и классификационный отчет.
```python
accuracy = accuracy_score(y_test, y_pred)
print(f"Точность модели: {accuracy:.2f}")
print(classification_report(y_test, y_pred))
```
Шаг 4: Интерпретация результатов
Посмотрим, какие факторы сильнее всего влияют на предсказания модели.
```python
feature_names = ['Pclass', 'Age', 'SibSp', 'Parch']
coefficients = log_model.coef_[0]
# Визуализируем влияние факторов
plt.figure(figsize=(8, 5))
sns.barplot(x=feature_names, y=coefficients)
plt.xlabel("Признаки")
plt.ylabel("Коэффициенты модели")
plt.title("Влияние факторов на вероятность выживания")
plt.show()
```
Вывод: если коэффициент у какого-то признака положительный, значит, этот фактор увеличивает вероятность выживания, а если отрицательный – снижает.
Сравнение и выводы
Линейная и логистическая регрессия применяются в разных задачах, но оба метода имеют схожий принцип работы.
– Линейная регрессия хорошо подходит для предсказания числовых значений, например, стоимости квартир. Ее коэффициенты позволяют понять, какие факторы оказывают наибольшее влияние на итоговое значение.
– Логистическая регрессия применяется в задачах классификации. Она предсказывает вероятность принадлежности к определенному классу, что полезно для медицинской диагностики, оценки риска отказа клиентов, предсказания выживаемости пассажиров и других задач.
Оба метода просты, эффективны и легко интерпретируются, что делает их отличным выбором для базовых задач машинного обучения.
Регуляризация: Ridge и Lasso
В машинном обучении линейные модели часто сталкиваются с проблемой переобучения, особенно если количество признаков велико или среди них есть коррелированные. В таких случаях модель может подстраиваться под шум в данных, что приводит к плохим результатам на новых примерах.
Чтобы решить эту проблему, применяют регуляризацию – метод, который добавляет штраф за сложность модели и тем самым ограничивает величину коэффициентов. Основные виды регуляризации для линейных моделей – Ridge (L2-регуляризация) и Lasso (L1-регуляризация).