Appearance
5. Визуализация распределений: Гистограммы и анализ частот
Построение частотных гистограмм через ax.hist()
Математический и инженерный смысл гистограмм в EDA
При проведении разведочного анализа данных (EDA) или анализе внутренних параметров нейросетей (весов, градиентов) инженеру важно знать не просто отдельные числа, а характер распределения величины. Мы должны понимать, какие значения встречаются часто, какие — редко, вокруг какого центра группируются данные и присутствуют ли в выборке аномальные скрытые выбросы.
Для решения этой задачи используется метод координатной сетки ax.hist(x). Он принимает на вход одномерную последовательность числовых значений x и строит частотную гистограмму.
Понятие «корзин» (bins) и дискретизация непрерывного диапазона
Физически гистограмма работает по следующему алгоритму:
- Находит минимальное и максимальное значения в массиве, определяя полный размах данных.
- Делит этот непрерывный диапазон на несколько равных интервалов — «корзин» (bins). По умолчанию Matplotlib создает 10 корзин.
- Подсчитывает, сколько элементов массива физически попало внутрь каждого интервала.
- Отрисовывает вертикальный столбик над каждой корзиной, высота которого строго пропорциональна количеству (частоте) попавших туда элементов.
Выбор оптимального параметра bins
Количество корзин (bins) — это важнейший гиперпараметр визуализации. Если выставить слишком маленькое значение (например, bins=2), график сожмет данные и скроет структуру распределения. Если выставить слишком большое значение (например, bins=100 для выборки из 50 элементов), график превратится в разрезанную «гребёнку», где большинство столбиков будут пустыми. Стандартным инженерным компромиссом для средних батчей данных является диапазон от 20 до 50 корзин.
python
import matplotlib.pyplot
fig, ax = matplotlib.pyplot.subplots()
# Simulated features dataset vector array
feature_values = [1.2, 1.4, 1.5, 2.1, 2.5, 2.6, 2.7, 3.5, 4.1]
# Drawing a histogram splitting data into 5 dense continuous bins
ax.hist(feature_values, bins=5)
ax.grid(True)Дебаг ошибок и выбросов в датасетах
Поиск брака и анализ распределения абсолютных ошибок (MAE)
В задачах регрессии (например, предсказание стоимости недвижимости или температуры) главным индикатором качества модели является вектор её ошибок: errors = y_true - y_pred. Пропустив этот вектор через ax.hist(), вы мгновенно увидите форму распределения ошибок. В идеальном случае гистограмма должна напоминать колокол (нормальное распределение) с центром в районе нуля. Если на графике виден длинный «хвост» в правой или левой части, это сигнализирует о систематическом сдвиге или наличии грубых аномалий (выбросов), которые модель не смогла обработать.
Управление наложением распределений через параметр alpha
Часто в ИИ требуется сравнить распределения двух величин на одной координатной сетке — например, сопоставить распределение весов до начала обучения и после завершения эпохи, или наложить график ошибок тренировочной выборки на валидационную.
Если просто вызвать метод ax.hist() дважды, столбики второго графика будут жестко непрозрачными и физически перекроют собой первый график. Чтобы этого избежать, используется параметр alpha (коэффициент прозрачности от 0.0 — полностью невидим, до 1.0 — абсолютно непрозрачен). Оптимальным значением для наложения слоев является alpha=0.5 или alpha=0.6.
python
import matplotlib.pyplot
fig, ax = matplotlib.pyplot.subplots()
# Overlaying two histograms layers using custom bins and alpha transparency channels
ax.hist(train_errors, bins=30, alpha=0.5, color="blue", label="Train Errors")
ax.hist(val_errors, bins=30, alpha=0.5, color="orange", label="Validation Errors")
ax.set_title("Errors Distribution Density Analysis")
ax.legend()
ax.grid(True)Чтение текущих границ осей: ax.get_ylim()
Метод ax.get_ylim() выполняет обратную операцию: возвращает кортеж (lower, upper) с текущими автоматически вычисленными границами оси Y. Это не инструмент ручного контроля, а механизм позиционирования: координаты вспомогательных объектов удобнее привязывать к фрейму графика, а не подбирать их вслепую в абсолютных единицах данных.
python
import numpy
import matplotlib.pyplot
# Simulated one-hour API latency log in milliseconds
latency = [18 + 12 * ((i % 7) / 6) + (340 if i % 250 == 0 else 0) for i in range(5000)]
p95 = numpy.percentile(latency, 95)
fig = matplotlib.pyplot.figure()
ax = fig.add_subplot(1, 1, 1)
ax.hist(latency, bins=40, color="steelblue", edgecolor="white")
# Vertical marker line at the 95th percentile boundary
ax.axvline(x=p95, color="crimson", linestyle="--")
# Anchoring the label inside the auto-computed upper Y boundary
ymax = ax.get_ylim()[1]
ax.text(p95 + 2, ymax * 0.85, f"p95 = {p95:.1f} ms", color="crimson")Без get_ylim() позицию надписи пришлось бы подбирать вручную, рискуя вывести текст за пределы видимой области. Полученное значение ymax гарантирует, что аннотация всегда останется внутри рассчитанной рамки графика.
Упражнения базовые (5 шт) (только с опорой на объясненную в данном уроке теорию)
1. Построение базовой частотной гистограммы
Задача: Дан массив числовых признаков metrics = [1.1, 1.2, 1.2, 2.5, 2.6, 2.7, 2.7, 2.7, 3.1]. Создайте холст и осей, постройте по этим данным гистограмму со значением по умолчанию для корзин и включите координатную сетку.
Посмотреть решение
python
import matplotlib.pyplot
metrics = [1.1, 1.2, 1.2, 2.5, 2.6, 2.7, 2.7, 2.7, 3.1]
# Instantiating default 10-bins histogram plot node
fig, ax = matplotlib.pyplot.subplots()
ax.hist(metrics)
ax.grid(True)2. Дискретизация диапазона через кастомные bins
Задача: На основе массива metrics из предыдущего упражнения постройте гистограмму, принудительно разбив весь числовой диапазон данных ровно на 4 корзины с помощью параметра bins=4. Выведите график.
Посмотреть решение
python
import matplotlib.pyplot
metrics = [1.1, 1.2, 1.2, 2.5, 2.6, 2.7, 2.7, 2.7, 3.1]
# Forcing exact continuous interval partitions counts
fig, ax = matplotlib.pyplot.subplots()
ax.hist(metrics, bins=4)
ax.grid(True)3. Текстовое аннотирование осей гистограммы
Задача: Постройте гистограмму для вектора абсолютных ошибок модели. Добавьте главный заголовок "Model Errors Histogram Analysis", подпись горизонтальной оси X — "Absolute Error Magnitude", подпись вертикальной оси Y — "Frequency Occurrences Count".
Посмотреть решение
python
import matplotlib.pyplot
errors = [0.1, 0.15, 0.02, 0.4, 0.55, 0.01, 0.11, 0.23, 0.04]
fig, ax = matplotlib.pyplot.subplots()
ax.hist(errors, bins=5)
# Attaching explicit metadata contexts definitions to structural graph text nodes
ax.set_title("Model Errors Histogram Analysis")
ax.set_xlabel("Absolute Error Magnitude")
ax.set_ylabel("Frequency Occurrences Count")
ax.grid(True)4. Наложение двух распределений с полупрозрачностью alpha
Задача: Даны два списка: group_first = [1, 2, 2, 3] и group_second = [2, 3, 3, 4]. Нарисуйте их гистограммы на одной координатной сетке. Сделайте первую группу синей ("blue"), вторую — красной ("red"), установив для обоих вызовов коэффициент прозрачности alpha=0.6. Добавьте легенду.
Посмотреть решение
python
import matplotlib.pyplot
group_first = [1, 2, 2, 3]
group_second = [2, 3, 3, 4]
fig, ax = matplotlib.pyplot.subplots()
# Layering styled histograms columns via alpha channel blending configurations
ax.hist(group_first, bins=3, alpha=0.6, color="blue", label="Group First")
ax.hist(group_second, bins=3, alpha=0.6, color="red", label="Group Second")
ax.legend()
ax.grid(True)5. Подавление бэкенд-массивов вывода в гистограммах
Задача: Метод ax.hist() возвращает сложный кортеж из трех массивов (значения частот, границы корзин, объекты отрисовки). Из-за этого в Jupyter над графиком печатается огромный блок системного текста. Напишите пример вызова гистограммы, заблокировав этот вывод с помощью точки с запятой ; в самом конце строки кода.
Посмотреть решение
python
import matplotlib.pyplot
data_samples = [10, 20, 20, 30]
fig, ax = matplotlib.pyplot.subplots()
# Trailing semicolon suppresses non-graphical terminal matrix arrays dump
ax.hist(data_samples, bins=2);Упражнения смешанные (5 шт) (включают материал прошлых уроков)
6. Headless-рендеринг гистограммы нормального распределения весов из NumPy
Задача: С помощью современного случайного генератора ИИ rng = numpy.random.default_rng(seed=42) сгенерируйте одномерный вектор из 1 000 случайных весов, подчиняющихся нормальному распределению со средним 0.0 и стандартным отклонением 1.0 (Урок 17 модуля NumPy). Переведите Matplotlib в режим работы без графического интерфейса (Урок 3 модуля Matplotlib). Создайте холст размером (9, 5) (Урок 2 модуля Matplotlib). Постройте частотную гистограмму весов, разбив диапазон строго на 40 корзин (Урок 5 модуля Matplotlib). Подпишите оси и сохраните полученную Гауссову кривую в файл "weights_distribution.png" (Урок 3 / Урок 4 модуля Matplotlib).
Посмотреть решение
python
import numpy
import matplotlib
# Activating server-side non-interactive execution engine (Lesson 3)
matplotlib.use('Agg')
import matplotlib.pyplot
# Generating Gaussian normal random tensor allocation (NumPy Lesson 17)
rng = numpy.random.default_rng(seed=42)
weights_tensor = rng.normal(loc=0.0, scale=1.0, size=1000)
# Configuring explicit plotting layout architectures (Matplotlib Lesson 2)
fig, ax = matplotlib.pyplot.subplots(figsize=(9, 5))
# Plotting dense frequency distributions histogram (Matplotlib Lesson 5)
ax.hist(weights_tensor, bins=40, color="purple", label="Weights Distribution")
ax.set_title("Neural Network Layer Weights Initialization Grid")
ax.set_xlabel("Weight Scalar Value")
ax.set_ylabel("Occurrences Density")
ax.legend()
ax.grid(True)
# Export byte data buffer assets to folder storage directly (Matplotlib Lesson 3)
fig.savefig("weights_distribution.png")7. Сравнительный анализ частот признаков датасета из Parquet-файла
Задача: Загрузите бинарный колоночный файл табличных признаков "features_vault.parquet" (Урок 8 модуля Pandas). С помощью двумерного оператора .loc[] извлеките полностью столбец "feature_raw_A" и столбец "feature_raw_B" (Урок 6 модуля Pandas). Настройте неинтерактивный режим работы (Урок 3 модуля Matplotlib). Нарисуйте гистограммы распределений обоих этих признаков на одной общей координатной сетке холста: для признака A задайте синий цвет, для признака B — оранжевый, выставив сквозной коэффициент прозрачности alpha=0.55 и количество корзин bins=30 (Урок 5 модуля Matplotlib). Снабдите график заголовком, легендой и экспортируйте в "features_comparison.png".
Посмотреть решение
python
import pandas
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot
# Loading columnar parquet records database from file system (Pandas Lesson 8)
features_df = pandas.read_parquet(path="features_vault.parquet")
# Slicing target named vectors channels components (Pandas Lesson 6)
data_vector_A = features_df.loc[:, "feature_raw_A"]
data_vector_B = features_df.loc[:, "feature_raw_B"]
fig, ax = matplotlib.pyplot.subplots()
# Blending overlaying histograms blocks charts together transparently (Matplotlib Lesson 5)
ax.hist(data_vector_A, bins=30, alpha=0.55, color="blue", label="Feature A")
ax.hist(data_vector_B, bins=30, alpha=0.55, color="orange", label="Feature B")
# Enforcing text labels metadata contexts declarations (Matplotlib Lesson 4)
ax.set_title("Comparative Exploratory Data Analysis (EDA)")
ax.set_xlabel("Feature Numeric Range Magnitude")
ax.set_ylabel("Density Frequency")
ax.legend()
ax.grid(True)
fig.savefig("features_comparison.png")8. Гистограмма ошибок регрессии для отслайсенного батча строк после очистки NaN
Задача: Дан DataFrame ответов модели: df_predictions = pandas.DataFrame({"true_y": [24.5, pandas.NA, 18.0, 31.2, 40.0], "pred_y": [23.0, 15.0, 19.5, 30.0, 35.0]}) (Урок 5 модуля Pandas). Жестко удалите из таблицы любые строки, содержащие маркеры пустот NaN по оси axis=0 (Урок 9 модуля Pandas). Вычислите вектор отклонений (ошибок) по векторизованной формуле: errors_vector = clean_df["true_y"] - clean_df["pred_y"] (Урок 7 модуля Pandas). Переведите Matplotlib в headless-режим (Урок 3). Постройте частотную гистограмму полученного вектора ошибок, окрасив столбики в зеленый цвет ("green") с параметром bins=5 (Урок 5 модуля Matplotlib). Проведите вертикальную реперную линию идеального нулевого сдвига ошибки x=0.0 красным пунктиром (Урок 4 модуля Matplotlib). Сохраните в "regression_errors.png".
Посмотреть решение
python
import pandas
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot
df_predictions = pandas.DataFrame({"true_y": [24.5, pandas.NA, 18.0, 31.2, 40.0], "pred_y": [23.0, 15.0, 19.5, 30.0, 35.0]})
# Step 1: Discard row slots containing computational NaN anomalies (Pandas Lesson 9)
clean_df = df_predictions.dropna(axis=0)
# Step 2: Compute element-wise residuals array (Pandas Lesson 7)
errors_vector = clean_df["true_y"] - clean_df["pred_y"]
# Step 3: Graphical rendering pipeline chart assembly (Matplotlib Lessons 2, 3 & 5)
fig, ax = matplotlib.pyplot.subplots()
ax.hist(errors_vector, bins=5, color="green", label="Residuals")
# Step 4: Overlay reference line indicators and text structures (Matplotlib Lesson 4)
ax.set_title("Regression Model Residuals Analysis Profile")
ax.set_xlabel("Prediction Error Deviation (True - Pred)")
ax.set_ylabel("Samples Count")
ax.axvline(x=0.0, color="red", linestyle="--", label="Ideal Prediction Zero")
ax.legend()
ax.grid(True)
fig.savefig("regression_errors.png")9. Анализ физического веса и гистограмма среза унаследованной матрицы весов
Задача: Создайте 2D-матрицу из диапазона целых чисел от 0 до 19 через numpy.arange(20).reshape(5, 4) (Урок 3 / Урок 11 модуля NumPy). Оберните её в таблицу pandas.DataFrame (Урок 5 модуля Pandas). С помощью позиционного оператора .iloc[] извлеките подматрицу средних трех строк (индексы 1, 2, 3), включая все столбцы (Урок 6 модуля Pandas). Сплющите полученную подматрицу в одномерный плоский 1D-вектор с помощью метода .ravel() без лишнего копирования памяти (Урок 18 модуля NumPy / Урок 2 модуля Pandas). В неинтерактивном режиме постройте гистограмму распределения значений этого плоского вектора, применив bins=6 (Урок 3 / Урок 5 модуля Matplotlib). Сохраните результат в файл "flattened_hist.png".
Посмотреть решение
python
import numpy
import pandas
import matplotlib
# Headless context block setup initialization (Lesson 3)
matplotlib.use('Agg')
import matplotlib.pyplot
# Generating core multi-dimensional integer grids tensors (NumPy Lessons 3 & 11)
numpy_grid = numpy.arange(20).reshape(5, 4)
dataset_df = pandas.DataFrame(numpy_grid)
# Extracting sub-dataset slice row indices boundaries (Pandas Lesson 6)
sub_df_slice = dataset_df.iloc[1:4, :]
# Collapsing multi-dimensional blocks coordinates down to a 1D vector tracking parent references (NumPy Lesson 18 & Pandas Lesson 2)
flat_values_vector = sub_df_slice.values.ravel()
# Render frequency statistics layout to disk directly (Matplotlib Lessons 2 & 5)
fig, ax = matplotlib.pyplot.subplots()
ax.hist(flat_values_vector, bins=6, color="teal")
ax.grid(True)
fig.savefig("flattened_hist.png")10. Сквозной поиск документации по распределениям и гистограммам в Jupyter
Задача: Напишите строку кода для выполнения в ячейке Jupyter Notebook, которая открывает интерактивную Docstring-инструкцию по встроенному методу построения гистограмм matplotlib.axes.Axes.hist с помощью символа интроспекции (Урок 1 модуля NumPy / Урок 1 модуля Pandas).
Посмотреть решение
python
import matplotlib.axes
# Running this statement inside a notebook layout pops up the comprehensive API configuration instructions
?matplotlib.axes.Axes.hist