/
cedric
/
ComputerVision
Обзор
Документация
Войти
/
cedric
/
ComputerVision
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
python/main.py
311 строк
14 KB
cedric
first_commit
25 дек 2025, 17:32
25 дек 2025, 17:32
23e9d7e
Код
Авторство
О чём код?
# Основные понятия распознавания образов на примере классификации цифр import numpy as np import matplotlib.pyplot as plt from sklearn import datasets, metrics, model_selection, preprocessing from sklearn.neighbors import KNeighborsClassifier from collections import Counter import time class PatternRecognitionDemo: """ Демонстрация основных понятий распознавания образов: 1. Объект (instance) - отдельное изображение 2. Признаки (features) - характеристики объектов 3. Классы (labels) - категории, к которым принадлежат объекты 4. Обучение (training) - настройка модели на размеченных данных 5. Классификация (classification) - отнесение новых объектов к классам """ def __init__(self): self.X_train, self.X_test = None, None self.y_train, self.y_test = None, None self.model = None self.load_data() def load_data(self): """Загрузка и подготовка данных (этап предобработки)""" print("1. ЗАГРУЗКА И ПОДГОТОВКА ДАННЫХ") print("=" * 50) # Загрузка датасета MNIST (упрощенная версия digits) digits = datasets.load_digits() X = digits.data # Матрица признаков (1797 изображений, 64 признака) y = digits.target # Вектор меток классов (цифры 0-9) print(f"Количество объектов: {X.shape[0]}") print(f"Количество признаков на объект: {X.shape[1]}") print(f"Количество классов: {len(np.unique(y))}") print(f"Классы: {np.unique(y)}") # Нормализация данных (важный этап предобработки) X_normalized = preprocessing.MinMaxScaler().fit_transform(X) # Разделение на обучающую и тестовую выборки self.X_train, self.X_test, self.y_train, self.y_test = model_selection.train_test_split( X_normalized, y, test_size=0.3, random_state=42, stratify=y ) print(f"\nРазмер обучающей выборки: {self.X_train.shape[0]}") print(f"Размер тестовой выборки: {self.X_test.shape[0]}") # Визуализация нескольких примеров self.visualize_samples(digits.images, y) def visualize_samples(self, images, labels): """Визуализация примеров изображений""" fig, axes = plt.subplots(2, 5, figsize=(10, 4)) fig.suptitle('Примеры изображений цифр (8x8 пикселей)', fontsize=14) for i, ax in enumerate(axes.flat): ax.imshow(images[i], cmap='gray', interpolation='nearest') ax.set_title(f'Класс: {labels[i]}') ax.axis('off') plt.tight_layout() plt.show() def extract_features_info(self): """Демонстрация извлечения признаков""" print("\n2. АНАЛИЗ ПРИЗНАКОВ") print("=" * 50) # Примеры признаков для первого изображения first_image_features = self.X_train[0] print(f"Признаки первого изображения (первые 10 из 64):") print(first_image_features[:10]) print(f"\nСтатистика по признакам:") print(f"Минимальное значение: {np.min(first_image_features):.3f}") print(f"Максимальное значение: {np.max(first_image_features):.3f}") print(f"Среднее значение: {np.mean(first_image_features):.3f}") # Гистограмма распределения значений признаков plt.figure(figsize=(10, 4)) plt.subplot(1, 2, 1) plt.hist(first_image_features, bins=20, edgecolor='black') plt.title('Распределение значений признаков') plt.xlabel('Значение признака') plt.ylabel('Частота') plt.subplot(1, 2, 2) plt.imshow(first_image_features.reshape(8, 8), cmap='hot') plt.title('Матрица признаков 8x8') plt.colorbar() plt.tight_layout() plt.show() def train_model(self): """Обучение модели классификатора""" print("\n3. ОБУЧЕНИЕ МОДЕЛИ РАСПОЗНАВАНИЯ") print("=" * 50) # Используем метод k-ближайших соседей (k-NN) self.model = KNeighborsClassifier( n_neighbors=5, # Количество соседей weights='distance', # Взвешивание по расстоянию metric='euclidean' # Евклидова метрика расстояния ) print("Модель: k-ближайших соседей (k-NN)") print(f"Параметры: k={self.model.n_neighbors}, " f"метрика={self.model.metric}") start_time = time.time() self.model.fit(self.X_train, self.y_train) training_time = time.time() - start_time print(f"Обучение завершено за {training_time:.3f} секунд") # Оценка на обучающей выборке train_accuracy = self.model.score(self.X_train, self.y_train) print(f"Точность на обучающей выборке: {train_accuracy:.3f}") def evaluate_model(self): """Оценка качества модели""" print("\n4. ОЦЕНКА КАЧЕСТВА РАСПОЗНАВАНИЯ") print("=" * 50) # Предсказание на тестовой выборке y_pred = self.model.predict(self.X_test) # Расчет метрик accuracy = metrics.accuracy_score(self.y_test, y_pred) precision = metrics.precision_score(self.y_test, y_pred, average='weighted') recall = metrics.recall_score(self.y_test, y_pred, average='weighted') print(f"Точность (accuracy): {accuracy:.3f}") print(f"Точность по классам (precision): {precision:.3f}") print(f"Полнота (recall): {recall:.3f}") # Матрица ошибок (confusion matrix) print("\nМатрица ошибок:") cm = metrics.confusion_matrix(self.y_test, y_pred) self.plot_confusion_matrix(cm) # Отчет по классификации print("\nОтчет по классификации:") report = metrics.classification_report(self.y_test, y_pred) print(report) # Визуализация примеров правильной и ошибочной классификации self.visualize_predictions(y_pred) def plot_confusion_matrix(self, cm): """Визуализация матрицы ошибок""" fig, ax = plt.subplots(figsize=(8, 6)) im = ax.imshow(cm, interpolation='nearest', cmap=plt.cm.Blues) ax.figure.colorbar(im, ax=ax) ax.set(title='Матрица ошибок', xlabel='Предсказанный класс', ylabel='Истинный класс', xticks=np.arange(10), yticks=np.arange(10), xticklabels=np.arange(10), yticklabels=np.arange(10)) # Добавление подписей thresh = cm.max() / 2. for i in range(cm.shape[0]): for j in range(cm.shape[1]): ax.text(j, i, format(cm[i, j], 'd'), ha="center", va="center", color="white" if cm[i, j] > thresh else "black") plt.tight_layout() plt.show() def visualize_predictions(self, y_pred): """Визуализация примеров классификации""" # Находим примеры правильных и ошибочных предсказаний correct_indices = np.where(y_pred == self.y_test)[0] incorrect_indices = np.where(y_pred != self.y_test)[0] fig, axes = plt.subplots(2, 5, figsize=(12, 5)) fig.suptitle('Примеры классификации (первые 5 правильных и 5 ошибок)', fontsize=14) # Правильные предсказания for i in range(5): if i < len(correct_indices): idx = correct_indices[i] ax = axes[0, i] ax.imshow(self.X_test[idx].reshape(8, 8), cmap='gray') ax.set_title(f'True: {self.y_test[idx]}, Pred: {y_pred[idx]}') ax.axis('off') # Ошибочные предсказания for i in range(5): if i < len(incorrect_indices): idx = incorrect_indices[i] ax = axes[1, i] ax.imshow(self.X_test[idx].reshape(8, 8), cmap='gray') ax.set_title(f'True: {self.y_test[idx]}, Pred: {y_pred[idx]}', color='red') ax.axis('off') plt.tight_layout() plt.show() def demonstrate_decision_process(self, sample_idx=0): """Демонстрация процесса принятия решения k-NN""" print("\n5. ПРОЦЕСС ПРИНЯТИЯ РЕШЕНИЯ (k-NN)") print("=" * 50) if sample_idx >= len(self.X_test): sample_idx = 0 test_sample = self.X_test[sample_idx].reshape(1, -1) true_label = self.y_test[sample_idx] # Находим k ближайших соседей distances, indices = self.model.kneighbors(test_sample) print(f"Тестовый пример (истинный класс: {true_label}):") print(f"Индексы {self.model.n_neighbors} ближайших соседей: {indices[0]}") print(f"Расстояния до соседей: {distances[0]}") print(f"Классы соседей: {self.y_train[indices[0]]}") # Голосование соседей neighbor_labels = self.y_train[indices[0]] label_counts = Counter(neighbor_labels) predicted_label = max(label_counts, key=label_counts.get) print(f"\nРезультат голосования: {dict(label_counts)}") print(f"Предсказанный класс: {predicted_label}") # Визуализация тестового примера и его соседей fig, axes = plt.subplots(1, 6, figsize=(15, 3)) fig.suptitle(f'Процесс классификации: пример {sample_idx}', fontsize=14) # Тестовый пример axes[0].imshow(test_sample.reshape(8, 8), cmap='gray') axes[0].set_title(f'Тест\nTrue: {true_label}') axes[0].axis('off') # 5 ближайших соседей for i in range(5): neighbor_idx = indices[0][i] neighbor_img = self.X_train[neighbor_idx].reshape(8, 8) neighbor_label = self.y_train[neighbor_idx] distance = distances[0][i] axes[i + 1].imshow(neighbor_img, cmap='gray') axes[i + 1].set_title(f'Сосед {i + 1}\nClass: {neighbor_label}\nDist: {distance:.3f}') axes[i + 1].axis('off') plt.tight_layout() plt.show() def run_full_demo(self): """Запуск полной демонстрации""" print("ДЕМОНСТРАЦИЯ ОСНОВ РАСПОЗНАВАНИЯ ОБРАЗОВ") print("=" * 60) self.extract_features_info() self.train_model() self.evaluate_model() self.demonstrate_decision_process() print("\n" + "=" * 60) print("ДЕМОНСТРАЦИЯ ЗАВЕРШЕНА") print("\nОсновные понятия, которые были продемонстрированы:") print("1. Данные и предобработка") print("2. Признаки и их извлечение") print("3. Обучение с учителем") print("4. Классификация и оценка качества") print("5. Принятие решений в моделях") # Запуск демонстрации if __name__ == "__main__": # Создание и запуск демо demo = PatternRecognitionDemo() demo.run_full_demo() # Дополнительно: простой пример классификации пользовательского ввода print("\n" + "=" * 60) print("ПРОСТОЙ ПРИМЕР КЛАССИФИКАЦИИ") # Можно добавить ручной ввод для тестирования try: # Создаем простую модель для демонстрации simple_model = KNeighborsClassifier(n_neighbors=3) simple_model.fit(demo.X_train, demo.y_train) # Тестируем на случайном примере random_idx = np.random.randint(0, len(demo.X_test)) test_sample = demo.X_test[random_idx].reshape(1, -1) prediction = simple_model.predict(test_sample)[0] print(f"\nСлучайный тестовый пример #{random_idx}:") print(f"Предсказанная цифра: {prediction}") print(f"Истинная цифра: {demo.y_test[random_idx]}") if prediction == demo.y_test[random_idx]: print("✓ Классификация верна!") else: print("✗ Классификация ошибочна") except Exception as e: print(f"Произошла ошибка: {e}")