или «Keras, объясни мне, что ты творишь»
"Нейросеть — это когда модель вдохновляется биологией, но всё равно спотыкается о пропущенное значение."
— разработчик, который пытался обучить сеть без нормализации
💡 Зачем нам нейросети?
Когда обычные модели уже не вытягивают сложность — на сцену выходят нейросети.
И нет, они не осознают себя, не читают мысли и не заменят маму. Они просто:
- Хорошо справляются с неструктурированными данными (картинки, текст, звук)
- Могут строить сложные зависимости, которые линейная регрессия даже не заметит
🧰 Что мы используем?
Для работы — только две библиотеки:
- TensorFlow — фреймворк машинного обучения от Google
- Keras — удобный интерфейс для построения моделей нейросетей, встроен в TensorFlow
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
👉 Комментарий: Никаких страшных слов вроде «градиентный спуск». Мы пойдём пошагово.
🎯 Задача 1: Нейросеть, которая угадывает оценки студентов
Мы уже делали это на линейной регрессии. Сейчас покажем, как работает нейросеть на том же.
📦 Данные:
import numpy as np
# 5 примеров: [часы учёбы, часы сна, часы в Dota]
X = np.array([
[2, 7, 3],
[3, 6, 2],
[4, 6, 1],
[5, 5, 1],
[6, 5, 0]
])
# Итоговые баллы
y = np.array([60, 65, 70, 80, 90])
🏗️ Построим нейросеть
model = keras.Sequential([
layers.Dense(10, activation='relu', input_shape=(3,)), # 1 скрытый слой из 10 нейронов
layers.Dense(1) # Выход — одно число (оценка)
])
👉 Комментарий:
- Sequential — модель, где слои идут друг за другом.
- Dense(10) — слой из 10 нейронов. Каждый нейрон связан со всеми входами.
- activation='relu' — функция, помогающая модели "учиться" только на полезных вещах (если совсем по-простому).
- input_shape=(3,) — потому что у нас 3 признака на входе.
- Dense(1) — выходной слой, предсказывает одно число — балл.
⚙️ Компиляция модели
model.compile(
optimizer='adam', # как обновлять веса (Adam — умный алгоритм оптимизации)
loss='mse', # функция ошибки (ошибка предсказания)
metrics=['mae'] # метрика, которую мы хотим отслеживать
)
🚀 Обучение
history = model.fit(X, y, epochs=100, verbose=0)
👉 Комментарий: Обучаем 100 эпох. Каждая эпоха — это один проход по всему датасету.
🔮 Предсказание
prediction = model.predict([[4, 6, 1]])
print(f"Предсказанная оценка: {prediction[0][0]:.1f}")
📊 Задача 2: Классификация — поступит ли студент
# Данные
X = np.array([
[3.0, 90], # GPA, балл по тесту
[2.5, 75],
[3.5, 85],
[2.0, 70],
[4.0, 95]
])
y = np.array([1, 0, 1, 0, 1]) # 1 — поступил, 0 — нет
# Модель
model = keras.Sequential([
layers.Dense(5, activation='relu', input_shape=(2,)),
layers.Dense(1, activation='sigmoid') # sigmoid — для задачи "да/нет"
])
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
model.fit(X, y, epochs=50, verbose=0)
# Проверим
test = np.array([[3.2, 82]])
result = model.predict(test)
print("Поступит" if result[0][0] > 0.5 else "Не поступит")
👉 Комментарий:
- sigmoid — выдаёт число от 0 до 1, удобно для классификации.
- binary_crossentropy — функция ошибки для бинарных задач.
🖼️ Задача 3: Распознавание цифр (MNIST)
from tensorflow.keras.datasets import mnist
from tensorflow.keras.utils import to_categorical
# Загружаем
(X_train, y_train), (X_test, y_test) = mnist.load_data()
# Нормализация
X_train = X_train / 255.0
X_test = X_test / 255.0
# Преобразуем y в категориальный вид (one-hot)
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)
# Строим модель
model = keras.Sequential([
layers.Flatten(input_shape=(28, 28)), # превращаем 2D картинку в 1D вектор
layers.Dense(128, activation='relu'),
layers.Dense(10, activation='softmax') # 10 классов — цифры 0–9
])
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(X_train, y_train, epochs=5, validation_data=(X_test, y_test))
👉 Комментарий:
- softmax — превращает выход в вероятности по всем 10 классам.
- categorical_crossentropy — подходит для многоклассовой классификации.
🧬 Задача 4: Ранжирование отзывов (настройка слоя Embedding)
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
# Примеры отзывов
texts = ["хороший фильм", "ужасно", "прекрасная игра актёров", "не понравилось", "гениально"]
labels = [1, 0, 1, 0, 1]
# Токенизация
tokenizer = Tokenizer()
tokenizer.fit_on_texts(texts)
sequences = tokenizer.texts_to_sequences(texts)
# Приведение к одной длине
X = pad_sequences(sequences, maxlen=4)
y = np.array(labels)
# Строим модель
model = keras.Sequential([
layers.Embedding(input_dim=50, output_dim=8, input_length=4), # 50 слов, 8 признаков
layers.Flatten(),
layers.Dense(1, activation='sigmoid')
])
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
model.fit(X, y, epochs=50, verbose=0)
👉 Комментарий:
- Embedding — превращает слова в векторы (word2vec внутри).
- pad_sequences — добавляет нули, если отзыв короче нужной длины.
⚙️ Задача 5: Регрессия на многослойной сети (предсказание стоимости жилья)
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
# Загружаем
data = fetch_california_housing()
X = data.data
y = data.target
# Масштабируем
scaler = StandardScaler()
X = scaler.fit_transform(X)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# Модель
model = keras.Sequential([
layers.Dense(64, activation='relu', input_shape=(X.shape[1],)),
layers.Dense(64, activation='relu'),
layers.Dense(1)
])
model.compile(optimizer='adam', loss='mse', metrics=['mae'])
model.fit(X_train, y_train, epochs=10, validation_data=(X_test, y_test))
🧾 Выводы
- Нейросеть — это последовательность слоёв, которые обучаются находить паттерны.
- Keras делает это удобно: Sequential → Dense → compile → fit → predict
⏭ Часть 5. ML в реальной жизни: с чего начать проект. Как не утонуть в датасетах