/
urfu_itis_limits
/
code-review-101-matfix
Обзор
Документация
Войти
/
urfu_itis_limits
/
code-review-101-matfix
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
master
assignment.py
332 строки
13 KB
matfix
update assignment.py
28 ноя 2025, 19:12
28 ноя 2025, 19:12
e3d8abf
Код
Авторство
О чём код?
""" Задание 10: Анализ датасета Digits - РЕАЛИЗАЦИЯ Цель: Анализ данных рукописных цифр - многоклассовая классификация """ import pandas as pd import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import load_digits # Конфигурация визуализации VISUALIZATION_CONFIG = { 'figsize_large': (15, 6), 'figsize_small': (15, 12), 'dpi': 300, 'colors': ['skyblue', 'lightgreen', 'lightcoral', 'gold'], 'edgecolor': 'black', 'colormap': 'hot' } plt.rcParams['font.sans-serif'] = ['DejaVu Sans'] plt.rcParams['axes.unicode_minus'] = False def load_data(): """Загрузить датасет Digits и конвертировать в DataFrame. Returns: pd.DataFrame""" try: digits = load_digits() except Exception as e: print(f"Ошибка загрузки данных: {e}") return None # Создаем DataFrame с пиксельными признаками и целевой переменной за одну операцию df = pd.DataFrame(digits.data, columns=[f'pixel_{i}' for i in range(64)]) df = df.assign(target=digits.target) return df def target_analysis(df): """Анализ целевой переменной (цифры 0-9). Returns: None""" print("\n" + "="*50) print("АНАЛИЗ ЦЕЛЕВОЙ ПЕРЕМЕННОЙ") print("="*50) # Распределение цифр target_counts = df['target'].value_counts().sort_index() print("Распределение цифр:") for digit, count in target_counts.items(): print(f"Цифра {digit}: {count} примеров") # Процентное распределение target_percent = (df['target'].value_counts(normalize=True) .sort_index() * 100) print("\nПроцентное распределение:") for digit, percent in target_percent.items(): print(f"Цифра {digit}: {percent:.2f}%") def feature_statistics(df): """Вычислить статистику по пиксельным значениям. Returns: None""" print("\n" + "="*50) print("СТАТИСТИКА ПИКСЕЛЬНЫХ ЗНАЧЕНИЙ") print("="*50) # Выбираем только пиксельные столбцы pixel_columns = [col for col in df.columns if col.startswith('pixel_')] pixel_data = df[pixel_columns] # Выносим values в переменную для оптимизации pixel_values = pixel_data.values print(f"Общая статистика по {len(pixel_columns)} пикселям:") print(f"Среднее значение: {pixel_values.mean():.4f}") print(f"Минимальное значение: {pixel_values.min()}") print(f"Максимальное значение: {pixel_values.max()}") print(f"Стандартное отклонение: {pixel_values.std():.4f}") print(f"Медиана: {np.median(pixel_values):.4f}") def create_bar_plot(ax, data, title, ylabel, color): """Вспомогательная функция для создания столбчатых диаграмм. Returns: None""" bars = ax.bar(data.index, data.values, color=color, edgecolor=VISUALIZATION_CONFIG['edgecolor']) ax.set_xlabel('Цифра') ax.set_ylabel(ylabel) ax.set_title(title) ax.set_xticks(range(10)) ax.grid(True, alpha=0.3) # Добавляем значения на столбцы for i, value in enumerate(data.values): ax.text(i, value + 0.5, f'{value:.2f}', ha='center', va='bottom', fontsize=9) return bars def create_visualization_safe(visualization_func, df, func_name): """Безопасное выполнение функций визуализации с обработкой ошибок. Returns: bool""" try: visualization_func(df) return True except Exception as e: print(f"Ошибка в {func_name}: {e}") return False def visualize_target(df): """Визуализировать распределение цифр. Returns: None""" fig, (ax1, ax2) = plt.subplots(1, 2, figsize=VISUALIZATION_CONFIG['figsize_large']) # Столбчатая диаграмма target_counts = df['target'].value_counts().sort_index() ax1.bar(target_counts.index, target_counts.values, color=VISUALIZATION_CONFIG['colors'][0], edgecolor=VISUALIZATION_CONFIG['edgecolor']) ax1.set_xlabel('Цифра') ax1.set_ylabel('Количество примеров') ax1.set_title('Распределение цифр в датасете') ax1.set_xticks(range(10)) # Добавляем значения на столбцы for i, count in enumerate(target_counts.values): ax1.text(i, count + 5, str(count), ha='center', va='bottom') # Круговая диаграмма colors = plt.cm.Set3(np.linspace(0, 1, 10)) wedges, texts, autotexts = ax2.pie( target_counts.values, labels=target_counts.index, autopct='%1.1f%%', colors=colors, startangle=90 ) ax2.set_title('Процентное распределение цифр') # Улучшаем читаемость for autotext in autotexts: autotext.set_color('black') autotext.set_fontweight('bold') plt.tight_layout() plt.savefig('10_digits_target_distribution.png', dpi=VISUALIZATION_CONFIG['dpi'], bbox_inches='tight') plt.show() def sample_digit_images(df): """Визуализировать примеры цифр. Returns: None""" fig, axes = plt.subplots(2, 5, figsize=VISUALIZATION_CONFIG['figsize_large']) axes = axes.flatten() # Выбираем по одному примеру для каждой цифры for digit in range(10): # Находим первый пример для текущей цифры с проверкой на пустоту digit_data = df[df['target'] == digit] if not digit_data.empty: sample = digit_data.iloc[0] # Извлекаем пиксели и преобразуем в матрицу 8x8 pixels = sample.drop('target').values.reshape(8, 8) # Отображаем изображение ax = axes[digit] ax.imshow(pixels, cmap='gray', interpolation='nearest') ax.set_title(f'Цифра: {digit}') ax.axis('off') else: # Если данных нет, создаем пустой subplot axes[digit].set_title(f'Цифра: {digit} (нет данных)') axes[digit].axis('off') plt.suptitle('Примеры рукописных цифр из датасета', fontsize=16) plt.tight_layout() plt.savefig('10_digits_sample_images.png', dpi=VISUALIZATION_CONFIG['dpi'], bbox_inches='tight') plt.show() def pixel_intensity_analysis(df): """Анализ интенсивности пикселей. Returns: None""" fig, axes = plt.subplots(2, 2, figsize=VISUALIZATION_CONFIG['figsize_small']) axes = axes.flatten() # Пиксельные столбцы (выносим в начало чтобы не дублировать) pixel_columns = [col for col in df.columns if col.startswith('pixel_')] pixel_values = df[pixel_columns].values # 1. Гистограмма всех пиксельных значений axes[0].hist(pixel_values.flatten(), bins=30, color=VISUALIZATION_CONFIG['colors'][0], edgecolor=VISUALIZATION_CONFIG['edgecolor'], alpha=0.7) axes[0].set_xlabel('Значение пикселя') axes[0].set_ylabel('Частота') axes[0].set_title('Распределение значений пикселей') axes[0].grid(True, alpha=0.3) # 2. Средняя интенсивность по цифрам mean_intensity = (df.groupby('target')[pixel_columns] .mean().mean(axis=1)) create_bar_plot(axes[1], mean_intensity, 'Средняя интенсивность пикселей по цифрам', 'Средняя интенсивность', VISUALIZATION_CONFIG['colors'][1]) # 3. Дисперсия пикселей по цифрам variance_by_digit = (df.groupby('target')[pixel_columns] .var().mean(axis=1)) create_bar_plot(axes[2], variance_by_digit, 'Дисперсия пикселей по цифрам', 'Средняя дисперсия', VISUALIZATION_CONFIG['colors'][2]) # 4. Среднее количество ненулевых пикселей non_zero_by_digit = (df.groupby('target') .apply(lambda x: (x[pixel_columns] > 0) .sum(axis=1).mean())) create_bar_plot(axes[3], non_zero_by_digit, 'Количество активных пикселей по цифрам', 'Среднее количество ненулевых пикселей', VISUALIZATION_CONFIG['colors'][3]) plt.suptitle('Анализ интенсивности и характеристик пикселей', fontsize=16) plt.tight_layout() plt.savefig('10_digits_pixel_analysis.png', dpi=VISUALIZATION_CONFIG['dpi'], bbox_inches='tight') plt.show() def heatmap_mean_images(df): """Тепловые карты средних изображений для каждой цифры. Returns: None""" fig, axes = plt.subplots(2, 5, figsize=VISUALIZATION_CONFIG['figsize_large']) axes = axes.flatten() pixel_columns = [col for col in df.columns if col.startswith('pixel_')] # Предварительно вычисляем все средние изображения для цифр с данными mean_images = {} available_digits = [] for digit in range(10): digit_data = df[df['target'] == digit] if not digit_data.empty: mean_image = digit_data[pixel_columns].mean().values.reshape(8, 8) mean_images[digit] = mean_image available_digits.append(digit) if not available_digits: print("Нет данных для создания тепловых карт") return # Вычисляем vmin и vmax только для доступных цифр all_mean_values = np.concatenate([img.flatten() for img in mean_images.values()]) vmin = np.min(all_mean_values) vmax = np.max(all_mean_values) # Создаем тепловые карты только для цифр с данными im = None for i, digit in enumerate(range(10)): ax = axes[i] if digit in mean_images: im = ax.imshow(mean_images[digit], cmap=VISUALIZATION_CONFIG['colormap'], interpolation='nearest', vmin=vmin, vmax=vmax) ax.set_title(f'Средняя цифра: {digit}') else: ax.set_title(f'Цифра: {digit} (нет данных)') ax.axis('off') # Добавляем общую цветовую шкалу только если есть данные if im is not None and available_digits: cbar = fig.colorbar(im, ax=axes.tolist(), orientation='horizontal', fraction=0.02, pad=0.04, shrink=0.8) cbar.set_label('Интенсивность пикселей') plt.suptitle('Тепловые карты средних изображений для каждой цифры', fontsize=16) plt.tight_layout() plt.savefig('10_digits_mean_heatmaps.png', dpi=VISUALIZATION_CONFIG['dpi'], bbox_inches='tight') plt.show() def main(): """Главная функция. Returns: None""" print("=" * 60) print("ЗАДАНИЕ 10: EXPLORATORY DATA ANALYSIS - DIGITS DATASET") print("=" * 60) try: df = load_data() if df is None: print("Не удалось загрузить данные") return print(f"\nДатасет загружен. Размер: {df.shape}") print("\nПервые 5 строк:") print(df.head()) target_analysis(df) feature_statistics(df) # Безопасное выполнение визуализаций visualizations = [ (visualize_target, "visualize_target"), (sample_digit_images, "sample_digit_images"), (pixel_intensity_analysis, "pixel_intensity_analysis"), (heatmap_mean_images, "heatmap_mean_images") ] successful_viz = 0 for viz_func, func_name in visualizations: if create_visualization_safe(viz_func, df, func_name): successful_viz += 1 print(f"\nУспешно выполнено визуализаций: {successful_viz}/{len(visualizations)}") except Exception as e: print(f"Критическая ошибка выполнения: {e}") return print("\n" + "=" * 60) print("Анализ завершен!") print("=" * 60) if __name__ == "__main__": main()