Кажется, прошло достаточно времени, чтобы написать вторую статью. По мере того, как я продолжаю изучать новые концепции, я одновременно участвую в личных проектах и ​​проектах колледжа, стремясь эффективно представить их здесь. Если вы обнаружите какие-либо ошибки или у вас есть отзывы, не стесняйтесь поделиться своими мыслями в комментариях или связаться со мной через мои каналы в социальных сетях (LinkedIn, GitHub или Instagram).

Введение

Основная цель проекта - использовать методы распознавания изображений для классификации изображений стойки на руках, отжиманий и скручиваний. Проект включает в себя несколько этапов, включая предварительную обработку, подготовку данных и обучение модели.

Первоначально изображения проходят предварительную обработку для обеспечения единообразия по размеру, формату и разрешению. Это включает в себя различные шаги, такие как изменение размера, нормализация и преобразование в оттенки серого.

Для обучения модели я пытался использовать популярные библиотеки глубокого обучения, такие как TensorFlow и Keras. Алгоритм YOLO (You Only Look Once), передовой алгоритм обнаружения объектов, основанный на сверточных нейронных сетях (CNN), также использовался для обнаружения и классификации объектов в режиме реального времени.

Кроме того, я пытаюсь использовать предварительно обученные модели, такие как DarkNet, чтобы ускорить обучение и повысить точность. Методы увеличения данных, такие как обрезка, вращение или отражение, были реализованы для увеличения разнообразия обучающих данных и повышения способности модели к обобщению.

В проекте используются библиотеки Python, такие как NumPy, OpenCV и ОС, для эффективного управления данными изображений, обработки изображений, предварительной обработки и визуализации результатов.

Примечание. Весь проект доступен в моем профиле GitHub под названием Обнаружение упражнений в репозитории Проекты.

Теория (необязательно)

Обработка изображений относится к обработке и анализу цифровых изображений с использованием компьютерных алгоритмов. Он включает в себя различные методы для улучшения, преобразования или извлечения информации из изображений. Вот обзор основных процессов или шагов, связанных с обработкой изображений:

1. Получение изображения. Первым шагом является захват или получение цифрового изображения с помощью таких устройств, как камеры, сканеры или датчики.

2. Предварительная обработка изображения. Этот этап включает подготовку полученного изображения для дальнейшего анализа. Он включает в себя такие операции, как изменение размера, обрезка, шумоподавление, коррекция цвета и улучшение для улучшения качества изображения и устранения любых артефактов или искажений.

3. Улучшение изображения. Методы улучшения направлены на улучшение визуального качества изображения за счет увеличения контрастности, регулировки яркости, повышения резкости краев или улучшения определенных функций. Эти методы можно применять глобально или локально, чтобы выделить нужные детали или улучшить общий вид.

4. Восстановление изображения. Методы восстановления используются для восстановления или реконструкции изображений, которые были ухудшены из-за шума, размытия или других типов искажений. Эти методы пытаются восстановить исходную информацию как можно точнее.

5. Сжатие изображения. Методы сжатия уменьшают размер изображения, сохраняя при этом важные детали. Это сделано для минимизации требований к объему памяти и оптимизации передачи по сетям без существенной потери качества. Общие методы сжатия включают алгоритмы сжатия без потерь и с потерями.

6. Сегментация изображения. Сегментация включает в себя разделение изображения на значимые области или объекты на основе таких характеристик, как цвет, текстура или интенсивность. Это помогает изолировать определенные области интереса или идентифицировать отдельные объекты на изображении.

7. Извлечение признаков. На этом этапе основное внимание уделяется выявлению и извлечению соответствующих признаков или закономерностей из изображений. Он включает в себя такие методы, как обнаружение краев, анализ текстуры, распознавание форм и обнаружение объектов для захвата и представления важной визуальной информации.

8. Распознавание/классификация объектов: в этом процессе изображения анализируются и помечаются для идентификации конкретных объектов или их классификации по заранее определенным категориям. Алгоритмы машинного обучения, такие как сверточные нейронные сети (CNN), обычно используются для задач распознавания и классификации объектов.

9. Анализ и интерпретация изображений. Этот последний шаг включает интерпретацию обработанных данных изображения для извлечения значимой информации или принятия обоснованных решений. Это может включать измерение и количественную оценку характеристик, выполнение статистического анализа или применение алгоритмов компьютерного зрения для извлечения информации более высокого уровня из изображения.

Переименование всех изображений в файл общего формата (.jpg)

# Function to rename multiple files
def main():
    i = 0

    for j in ['Crunches/', 'Handstands/', 'Planks/']:
        path = "./path/Data/" + j

        for filename in os.listdir(path):
            my_dest = j + str(i) + ".jpg"
            my_source = path + filename
            print(my_source)
            my_dest = path + my_dest
            print(my_dest)
            os.rename(my_source, my_dest) # rename() function will rename all the files
            i += 1

# Driver Code
if __name__ == '__main__':
    # Calling main() function
    main()

Предоставленная пользовательская функция выполняет преобразование имен изображений в соответствующие имена, такие как «crunches_0.jpg», «HandStands_40.jpg» и «planks_80.jpg». Кроме того, он гарантирует, что все изображения имеют единый формат файла, преобразовывая их расширения в общий формат, который называется «jpg».

Для выполнения кода необходимо иметь главную папку для всего проекта. Внутри этой основной папки должна быть отдельная папка, предназначенная для тренировочных данных, далее организованная в подпапки с названиями «Скручивания», «Планки» и «Стойки на руках». Не забудьте обновить переменную «путь» в коде соответствующим значением пути, отражающим фактическую файловую структуру в вашей системе.

Импорт набора данных

# importing all the necessary libraries
import glob
import cv2
import matplotlib.pyplot as plt

# importing all the data
crunches = [cv2.imread(file) for file in glob.glob("./path/Crunches/*.jpg")]
planks = [cv2.imread(file) for file in glob.glob("./path/Planks/*.jpg")]
handstands = [cv2.imread(file) for file in glob.glob("./path/HandStands/*.jpg")]

Приведенный выше код импортирует все изображения в виде массивов numpy порядка 3x3x3 (строки x столбцы x цветовые каналы) и сохраняет их в соответствующих отдельных переменных. Вы можете просматривать изображения с помощью функции .imshow() библиотеки matplotlib, как показано ниже:

# Viewing a 'crunches' image
plt.title("Crunches")
plt.xlabel("X pixel scaling")
plt.ylabel("Y pixels scaling")
 
image = crunches[0] # Selecting the 1st image from all the cruches images

# cv2 by default imports images into BGR format
# so, you will need to convert them into RGB using .cvtColor()
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)) # Printing the image in RGB format
plt.show()

Извлечение функций через YOLO (необязательно)

# Load Yolo
net = cv2.dnn.readNet("yolov3.weights", "yolov3.cfg")
classes = []
with open("coco.names", "r") as f:
    classes = [line.strip() for line in f.readlines()]

layer_names = net.getLayerNames()
output_layers = [layer_names[i - 1] for i in net.getUnconnectedOutLayers()]
colors = np.random.uniform(0, 255, size=(len(classes), 3))

# Input and Output folder paths
input_folder_path = "path/Crunches"
output_folder_path = 'path/Output Images/'

# Loop through all the images in the input folder
for filename in os.listdir(input_folder_path):
    if filename.endswith(".jpg"):
        # Load image
        img_path = os.path.join(input_folder_path, filename)
        img = cv2.imread(img_path)
        img = cv2.resize(img, None, fx=0.4, fy=0.4)
        height, width, channels = img.shape

        # Detect objects
        blob = cv2.dnn.blobFromImage(img, 0.00392, (416, 416), (0, 0, 0), True, crop=False)
        net.setInput(blob)
        outs = net.forward(output_layers)

        # Initialize variables to store information about detected objects
        class_ids = []
        confidences = []
        boxes = []

        # Iterate over all detected objects
        for out in outs:
            for detection in out:
                scores = detection[5:]
                class_id = np.argmax(scores)
                confidence = scores[class_id]
                if confidence > 0.5:
                    # Object detected
                    center_x = int(detection[0] * width)
                    center_y = int(detection[1] * height)
                    w = int(detection[2] * width)
                    h = int(detection[3] * height)

                    # Rectangle coordinates
                    x = int(center_x - w / 2)
                    y = int(center_y - h / 2)

                    boxes.append([x, y, w, h])
                    confidences.append(float(confidence))
                    class_ids.append(class_id)

        # Remove redundant bounding boxes using Non-Maximum Suppression
        indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4)

        # Draw bounding boxes and labels on the image
        font = cv2.FONT_HERSHEY_PLAIN
        for i in range(len(boxes)):
            if i in indexes:
                x, y, w, h = boxes[i]
                label = str(classes[class_ids[i]])
                color = colors[i]
                cv2.rectangle(img, (x, y), (x + w, y + h), color, 2)
                cv2.putText(img, label, (x, y + 30), font, 3, color, 3)

        # Save the output image in the output folder
        output_path = os.path.join(output_folder_path, filename)
        cv2.imwrite(output_path, img)

        cv2.waitKey(0)
        cv2.destroyAllWindows()

Предоставленный блок кода является необязательным компонентом и не является обязательным для выполнения; Я не буду выполнять это в настоящее время. Его цель — перебирать изображения в указанной входной папке и выполнять обнаружение объектов на каждом изображении. После успешного обнаружения человека (объекта) на изображении вы можете заменить исходное изображение обрезанной версией, содержащей только обнаруженное лицо. Этот процесс направлен на улучшение обучения модели, сосредоточив внимание исключительно на соответствующих человеческих субъектах на изображениях.

Увеличение данных

Увеличение данных — это метод, обычно используемый в машинном обучении и компьютерном зрении для искусственного увеличения размера и разнообразия обучающего набора данных. Он включает в себя применение различных преобразований или модификаций к существующим образцам данных, что приводит к новым и измененным версиям исходных данных.

# Flipping all the images horizonally
crunches_flipped = []
hand_stands_flipped = []
planks_flipped = []

for i in crunches:
    crunches_flipped.append(cv2.flip(i, 1))

for j in hand_stands:
    hand_stands_flipped.append(cv2.flip(j, 1))

for k in planks:
    planks_flipped.append(cv2.flip(k, 1))

# Creating lists of all the primary and the flipped images
crunches_final = crunches + crunches_flipped
hand_stands_final = hand_stands + hand_stands_flipped
planks_final = planks + planks_flipped

Предоставленный блок кода фокусируется на горизонтальном переворачивании изображений как средстве увеличения обучающих данных и улучшения процесса обучения модели. Он включает в себя сохранение перевернутых изображений в пустом списке и последующее добавление всех изображений определенного класса в другой список. Этот процесс эффективно расширяет набор данных и способствует улучшению обучения модели. Перевернутые изображения выглядят примерно так:

Преобразование в оттенки серого

# all the images will be stored in these empty lists
crunches_gray = []
hand_stands_gray = []
planks_gray = []

# iterating through images of all the 3 classes individually and converting
# them through the .COLOR_BGR2GRAY function
for i in crunches_final:
    crunches_gray.append(cv2.cvtColor(i, cv2.COLOR_BGR2GRAY))

for j in hand_stands_final:
    hand_stands_gray.append(cv2.cvtColor(j, cv2.COLOR_BGR2GRAY))

for k in planks_final:
    planks_gray.append(cv2.cvtColor(k, cv2.COLOR_BGR2GRAY))

Предоставленный блок кода выполняет итерацию по изображениям в каждом классе отдельно. Во время этой итерации каждое изображение отдельно преобразуется в формат оттенков серого, а затем добавляется в пустой список, относящийся к этому конкретному классу. Результирующие изображения в градациях серого будут выглядеть следующим образом:
Примечание. Фактическое отображение изображений в градациях серого может различаться в зависимости от используемой системы или программного обеспечения.

# Viewing a 'crunches' image
plt.title("Crunches")
plt.xlabel("X pixel scaling")
plt.ylabel("Y pixels scaling")
 
image = crunches_gray[40] # Selecting an image from all the cruches images
plt.imshow(image) # Printing the image in GRAY format
plt.show()

Изменение размера изображений

Чтобы обучить модель для проекта распознавания изображений, необходимо, чтобы все изображения были в единообразном размерном формате. Поэтому для этого мы конвертируем все изображения в стандартизированный размер 300x300x3. Предоставленный код демонстрирует процесс преобразования изображений в желаемые размеры.

# Defining the dimensions of the new images
newsize = (300, 300)

# Resizing all the 3 class of images
crunches_resized = []
hand_stands_resized = []
planks_resized = []

for i in crunches_gray:
    crunches_resized.append(cv2.resize(i, newsize))

for j in hand_stands_gray:
    hand_stands_resized.append(cv2.resize(j, newsize))
    
for k in planks_gray:
    planks_resized.append(cv2.resize(k, newsize))
# Viewing a 'planks' image
plt.title("Planks")
plt.xlabel("X pixel scaling")
plt.ylabel("Y pixels scaling")
 
plt.imshow(planks_resized[54])
plt.show()

Создание фрейма данных

Для эффективного обучения модели данные, такие как изображения, необходимо структурировать. В данном конкретном случае было два варианта. Первый вариант заключался в использовании более сложного подхода с использованием функции tf.keras.utils.image_dataset_from_directory, которая автоматически обрабатывает создание структурированного набора данных.

# tf method
tf.keras.utils.image_dataset_from_directory(
    directory,
    labels='inferred',
    label_mode='int',
    class_names=None,
    color_mode='rgb',
    batch_size=32,
    image_size=(256, 256),
    shuffle=True,
    seed=None,
    validation_split=None,
    subset=None,
    interpolation='bilinear',
    follow_links=False,
    crop_to_aspect_ratio=False,
    **kwargs
)

Альтернативой было ручное управление массивами с помощью пользовательских функций. Учитывая более ранний шаг преобразования изображений в согласованный размер 300x300, результирующие изображения будут иметь внешний вид, аналогичный следующему:

image1 [row_1 [[col_1], [col_2], …, [col_300] ],
[row2 [col_1], [col_2], …, [col_300] ], ….
[row300 [col_1], [col_2], …, [col_300] ] ]

crunches_resized[0]

Output: array([[244, 244, 244, ..., 239, 239, 239],
       [244, 244, 244, ..., 239, 239, 239],
       [244, 244, 244, ..., 239, 239, 239],
       ...,
       [204, 205, 206, ..., 198, 198, 198],
       [204, 205, 206, ..., 199, 199, 199],
       [204, 205, 206, ..., 200, 200, 200]], dtype=uint8)

Далее наша задача состоит в том, чтобы преобразовать каждое изображение в отдельный экземпляр, охватывающий 90 000 функций или пикселей (в результате размеров 300x300). Это преобразование может быть достигнуто с помощью двух пользовательских функций, описанных ниже. Важно отметить, что время выполнения может варьироваться в зависимости от вычислительных возможностей системы.

# User-defined function to convert a single image to one single list
def convert_single_img(matrix):
    final_image = [] # converted row
    #Iterating through rows (x axis)
    for x in matrix:
        #Iterating throug columns (y axis)
        for y in x:
            final_image.append(y)    
    
    return final_image
# User-defined function to convert all the images to one into 1 single lists respectively
def convert_all_img(store):
    final_images = []
    for img in store:
        converted_img = convert_single_img(img)
        final_images.append(converted_img)
        
    return final_images
# Applying the above user-defined function to the data 
# and generating class categories for the same
crunches_data  = convert_all_img(crunches_resized)
crunches_target = ["Crunches" for x in range(0,80)] 

planks_data =  convert_all_img(planks_resized)
planks_target = ["Plank" for x in range(0,80)]

hand_stands_data =  convert_all_img(hand_stands_resized)
hand_stands_target = ["Hand Stand" for x in range(0,80)]

# we have selected the range as (0, 80) as each class initially had 40 images
# and after flipping them horizontally, we double the images.
# for easier understanding, you can take the range as length of either 
# crunch_resized, planks_resized or hand_stands_resized. 
# Concatincating and merging all the classes into one 
exercise_data_raw = crunches_data + planks_data + hand_stands_data 
exercise_target_raw = crunches_target + planks_target + hand_stands_target

Теперь, когда данные объединены в единый массив, а каждый экземпляр сопоставлен с соответствующим классом, следующим шагом будет перетасовка данных и разделение их на подмножества для обучения и тестирования. Этот процесс позволяет нам обеспечить случайность в распределении данных и установить отдельные наборы данных для обучения и оценки модели.

# Shuffling the data for increasing the efficiency while training
# and assigning each image their respective classes

import random
random.seed(1) # setting a seed value to avoid change of values when re-runed

# create an array of numbers corresponding to total number of images
index = [x for x in range(0,240)] 
# shuffling the indexes
random.shuffle(index)

# storing all the final image instances into these lists
exercise_data = []
exercise_target = []

# iterating thorugh index, exercise_data_raw and exercise_target_raw together
# and appending index_i th element into list along with its respective 
for index_i in index:
    exercise_data.append(exercise_data_raw[index_i])
    exercise_target.append(exercise_target_raw[index_i])

В предоставленном фрагменте кода создается список перетасованных индексов. Затем, перебирая массивы exercide_data_raw и exercise_target_raw, выбираются случайные элементы в порядке, указанном массивом индексов. Каждый выбранный элемент вместе с соответствующим ему классом добавляется в соответствующие списки, а именно exercise_target и exercise_data. Этот процесс гарантирует, что элементы выбираются случайным образом и правильно связываются с соответствующими классами во вновь созданных списках.

Учитывая некоторую неуверенность в правильности логики, я создал функцию обратного преобразования в качестве средства проверки. Цель этой функции — гарантировать, что при восстановлении одиночных экземпляров, которые ранее были преобразованы в массив 300x300, они формировали правильное изображение без каких-либо искажений. Этот дополнительный шаг обеспечивает уверенность и подтверждение точности и целостности процесса преобразования данных. Вот как вы можете попробовать это:

# User-defined function to convert images back to the matrix form
def inverseTransform(image):
    start = 0
    end = 300 # number of columns
    transformed_image = []
    
    for i in range(0, 90000): # total number of pixels
        if start == len(image):
            break
        transformed_image.append(image[start:end])
        start += 300
        end += 300
    return transformed_image
# you can select any random image but don't forget to pop the last empty 
# sub-list
validate = inverseTransform(exercise_data[85])
validate.pop()
# Plotting the validation image
plt.imshow(validate)
plt.show() 

Для тех из вас, кто следил за частью обработки изображений, это знаменует собой заключение. Если вы обнаружите какие-либо ошибки в предыдущем содержании, не стесняйтесь посетить мой GitHub и оставить свой отзыв. Если у вас есть дополнительные вопросы или предложения, не стесняйтесь обращаться ко мне в LinkedIn или Instagram.

Следующий раздел является дополнительным и может рассматриваться как дополнительное упражнение для изучения и экспериментирования.

Обучение моделей (необязательно)

Увы! Вы дожили до этого места!
В этом конкретном проекте колледжа я стремился повысить его привлекательность, проведя настройку гиперпараметров. Это включало изменение параметров в нескольких моделях, включая логистическую регрессию, классификатор дерева решений, классификатор случайного леса и KNN, как с включением PCA, так и без него.

PCA или Principal Component Analysis, популярный метод уменьшения размерности, используемый для преобразования многомерного набора данных в низкоразмерное представление. Он направлен на захват наиболее важных закономерностей или особенностей данных путем определения набора ортогональных осей, называемых главными компонентами.

После обучения данных с использованием традиционных алгоритмов машинного обучения я приступил к сравнению их производительности с моделью, обученной CNN. Этот шаг позволил мне оценить эффективность и относительные достоинства различных подходов, использованных в этом проекте.

Чтобы оптимизировать использование времени, я выполнил все коды одновременно, охватив четыре различных сценария: 1) PCA с логистической регрессией, деревом решений и классификатором случайного леса; 2) без PCA с логистической регрессией, деревом решений и классификатором случайного леса; 3) ППШ с КНН; и 4) Без PCA с KNN. Чтобы добиться параллельного выполнения этих моделей, необходимо было экспортировать переменную, содержащую сохраненные данные, включая значения пикселей и соответствующие им целевые переменные. Таким образом, я смог ускорить процесс, обеспечив при этом точный и эффективный анализ.

Прежде чем приступить к вышеупомянутым задачам, необходимо выполнить последний шаг предварительной обработки. Этот шаг включает в себя метку, кодирующую целевую переменную, чтобы преобразовать ее в числовой формат. Применяя кодирование меток, целевая переменная преобразуется в представление, которое легко понять и обработать с помощью различных алгоритмов. Этот подготовительный шаг обеспечивает совместимость с последующими операциями и облегчает эффективный анализ и интерпретацию данных.

# --- Label Encoding the target variables ---

from sklearn.preprocessing import LabelEncoder
exercise_target = LabelEncoder().fit_transform(exercise_target)
# --- Exporting data and target values ---
# this is to be executed only once

import numpy as np

# exporting the features (data)
np.savetxt('exercise_data.csv', exercise_data, delimiter=',')

# exporting the classes (target)
with open('exercise_target.txt', 'w') as file:
    for data in exercise_data:
        file.write(str(data) + '\n')
# --- How to import the data ---
# this is to be imported in every notebook while training the model

# Importing the target data
with open('path/exercise_target.txt', 'r') as f:
    target = f.readlines()
 
for i in range(len(target)):
    target[i] = target[i][0]

# Importing the features as a dataframe
import pandas as pd
data = pd.read_csv("path/exercise_data.csv", header = None)

После успешного импорта данных мы можем приступить к настройке гиперпараметров. Для этого откройте четыре разных файла Python и выполните соответствующие блоки кода в каждом из них. Стоит отметить, что с моей стороны произошла ошибка, повлекшая за собой чрезмерное количество случайных состояний. Пожалуйста, не стесняйтесь уменьшать количество случайных состояний по мере необходимости при попытке кода.

# --- 1] PCA: LogisticRegression, DecisionTreeClassifier, RandomForestClassifier ---

# importing all the necessary libraries

# import random 
from sklearn.decomposition import PCA # Dimensionality Reduction
from sklearn.model_selection import train_test_split # Training-Testing
from sklearn.linear_model import LogisticRegression # Model 1
from sklearn.tree import DecisionTreeClassifier # Model 2
from sklearn.ensemble import RandomForestClassifier # Model 3
from sklearn.metrics import accuracy_score # evaluation metric
from sklearn.metrics import f1_score # evaluation metric
import time # computation time

'''
# Generating random_state values
random.seed(235)
random_states = []
for i in range(18):
    random_number = random.randint(0, 1000)
    random_states.append(random_number)
'''

# Defining values of the parameters

random_states = [355, 742, 527, 788, 38, 254, 77, 93, 22, 257, 904, 161, 56, 120, 63, 891, 853, 479]
n_comps = n_comps = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 200, 240]
models = [LogisticRegression(), DecisionTreeClassifier(), RandomForestClassifier()]

# Definging the dataframe and its attributes
accuracy_dataframe = pd.DataFrame(columns = ['PCA Status', 'Algorhythm', 'n_components', 'Computation Time', 'random_state', 'Accuracy Score', 'F1 score'])

for i in models:
    for j in n_comps:
        for k in random_states:

            # Storing all the values in this empty dictionary
            acc_dict = {}
            
            # applying PCA on the features
            X = exercise_data
            y = exercise_target
            
            # Starting the time counter
            start_time = time.time()
            
            pca = PCA(n_components = j)
            pca.fit_transform(X)
            
            # Model Training 
            i.set_params(random_state = k)

            # Data Splitting
            X_train, X_test, y_train, y_test = train_test_split(X, y)
            # Model Training
            i.fit(X_train, y_train)

            # Ending the time counter
            time_taken = time.time() - start_time

            # Prediction
            y_pred = i.predict(X_test)
            
            acc_dict['PCA Status'] = 'Yes'
            acc_dict['Algorhythm'] = i
            acc_dict['n_components'] = j
            acc_dict['Computation Time'] = time_taken
            acc_dict['random_state'] = k
            acc_dict['Accuracy Score'] = accuracy_score(y_test, y_pred)
            acc_dict['F1 score'] = f1_score(y_test, y_pred, average='weighted')
            print(acc_dict)

            accuracy_dataframe = accuracy_dataframe.append(acc_dict, ignore_index=True)

# Exporting all the data to save the data
accuracy_dataframe.to_excel('Accuracy_wPCA_1.xlsx', index = False)
# --- 2] W/O PCA: LogisticRegression, DecisionTreeClassifier, RandomForestClassifier ---

# importing all the necessary libraries

from sklearn.model_selection import train_test_split # Training-Testing
from sklearn.linear_model import LogisticRegression # Model 1
from sklearn.tree import DecisionTreeClassifier # Model 2
from sklearn.ensemble import RandomForestClassifier # Model 3
from sklearn.metrics import accuracy_score # evaluation metric
from sklearn.metrics import f1_score # evaluation metric
import time # computation time

# Defining values of the parameters

random_states = [355, 742, 527, 788, 38, 254, 77, 93, 22, 257, 904, 161, 56, 120, 63, 891, 853, 479]
models = [LogisticRegression(), DecisionTreeClassifier(), RandomForestClassifier()]

# Definging the dataframe and its attributes
accuracy_dataframe_wo = pd.DataFrame(columns = ['PCA Status', 'Algorhythm', 'n_components', 'Computation Time', 'random_state', 'Accuracy Score', 'F1 score'])

for i in models:
    for k in random_states:

        # Storing all the values in this empty dictionary
        acc_dict = {}
        
        # Defining the features and the target variables
        X = data
        y = target

        # Starting the time counter
        start_time = time.time()

        # Setting up random states
        i.set_params(random_state = k)

        # Data Splitting
        X_train, X_test, y_train, y_test = train_test_split(X, y)
        # Model Training
        i.fit(X_train, y_train)

        # Ending the time counter
        time_taken = time.time() - start_time

        # Prediction
        y_pred = i.predict(X_test)

        acc_dict['PCA Status'] = 'No'
        acc_dict['Algorhythm'] = i
        acc_dict['Computation Time'] = time_taken
        acc_dict['random_state'] = k
        acc_dict['Accuracy Score'] = accuracy_score(y_test, y_pred)
        acc_dict['F1 score'] = f1_score(y_test, y_pred, average='weighted')
        print(acc_dict)

        accuracy_dataframe_wo = accuracy_dataframe_wo.append(acc_dict, ignore_index=True)

# Exporting all the data to save the data
accuracy_dataframe_wo.to_excel('Accuracy_woPCA_1.xlsx', index = False)
# --- 3] PCA: KNeighborsClassifier ---

# importing all the necessary libraries

from sklearn.decomposition import PCA # Dimensionality Reduction
from sklearn.model_selection import train_test_split # Training-Testing
from sklearn.neighbors import KNeighborsClassifier as KNN # model
from sklearn.metrics import accuracy_score # evaluation metric
from sklearn.metrics import f1_score # evaluation metric
import time # computation time

# Defining values of the parameters

n_comps = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 200, 240]
ks = [2, 3, 5, 8, 10, 15, 20]
models = [KNN()]

# Definging the dataframe and its attributes
accuracy_dataframe = pd.DataFrame(columns = ['PCA Status', 'Algorhythm', 'n_components', 'Computation Time', 'random_state', 'Accuracy Score', 'F1 score'])

for i in models:
    for j in n_comps:
        for k in ks:

            # Storing all the values in this empty dictionary
            acc_dict = {}
            
            # applying PCA on the features
            X = data
            y = target
            
            # Starting the time counter
            start_time = time.time()
            
            pca = PCA(n_components = j)
            pca.fit_transform(X)

            # Model Training 
            i.set_params(n_neighbors = k)

            # Data Splitting
            X_train, X_test, y_train, y_test = train_test_split(X, y)
            # Model Training
            i.fit(X_train, y_train)

            # Ending the time counter
            time_taken = time.time() - start_time

            # Prediction
            y_pred = i.predict(X_test)
            
            acc_dict['PCA Status'] = 'Yes'
            acc_dict['Algorhythm'] = i
            acc_dict['n_components'] = j
            acc_dict['Computation Time'] = time_taken
            acc_dict['random_state'] = k
            acc_dict['Accuracy Score'] = accuracy_score(y_test, y_pred)
            acc_dict['F1 score'] = f1_score(y_test, y_pred, average='weighted')
            print(acc_dict)

            accuracy_dataframe = accuracy_dataframe.append(acc_dict, ignore_index=True)

# Exporting all the data to save the data
accuracy_dataframe.to_excel('Accuracy_wPCA_2.xlsx', index = False)
# --- 4] W/O PCA: KNeighborsClassifier ---

# importing all the necessary libraries

from sklearn.model_selection import train_test_split # Training-Testing
from sklearn.neighbors import KNeighborsClassifier as KNN # model
from sklearn.metrics import accuracy_score # evaluation metric
from sklearn.metrics import f1_score # evaluation metric
import time # computation time

# Defining values of the parameters

ks = [2, 3, 5, 8, 10, 15, 20]
models = [KNN()]

# Definging the dataframe and its attributes
accuracy_dataframe_wo = pd.DataFrame(columns = ['PCA Status', 'Algorhythm', 'n_components', 'Computation Time', 'random_state', 'Accuracy Score', 'F1 score'])

for i in models:
    for k in ks:

        # Storing all the values in this empty dictionary
        acc_dict = {}

        # Defining the features and the target variables
        X = data
        y = target

        # Starting the time counter
        start_time = time.time()

        # Model Training 
        i.set_params(n_neighbors = k)

        # Data Splitting
        X_train, X_test, y_train, y_test = train_test_split(X, y)
        # Model Training
        i.fit(X_train, y_train)

        # Ending the time counter
        time_taken = time.time() - start_time

        # Prediction
        y_pred = i.predict(X_test)

        acc_dict['PCA Status'] = 'No'
        acc_dict['Algorhythm'] = i
        acc_dict['Computation Time'] = time_taken
        acc_dict['random_state'] = k
        acc_dict['Accuracy Score'] = accuracy_score(y_test, y_pred)
        acc_dict['F1 score'] = f1_score(y_test, y_pred, average='weighted')
        print(acc_dict)

        accuracy_dataframe_wo = accuracy_dataframe_wo.append(acc_dict, ignore_index=True)

accuracy_dataframe_wo.to_excel('Accuracy_woPCA_2.xlsx', index = False)

После выполнения этих фрагментов кода вы получите четыре выходных файла Excel с именами «Accuracy_wPCA_1», «Accuracy_wPCA_2», «Accuracy_woPCA_1» и «Accuracy_woPCA_2». Объедините файлы, содержащие PCA (wPCA), в один объединенный файл (с именем «Accuracy_wPCA») и аналогичным образом объедините файлы без PCA (woPCA) в другой объединенный файл (с именем «Accuracy_woPCA»). Полученные объединенные файлы будут иметь структуру, похожую на следующую:

Перед выбором оптимальной модели из вышеупомянутых вариантов целесообразно оценить их характеристики с помощью базового разведочного анализа данных (EDA). Ниже приведены некоторые задачи EDA, которые я уже выполнил:

# Importing the necessary libraries
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

# importing the datasets
df_wPCA = pd.read_excel("Accuracy_wPCA.xlsx")
df_woPCA = pd.read_excel("Accuracy_woPCA.xlsx")
# --- 1] With PCA: Algorhythm vs Accuracy Score --- 

sns.catplot(data = df_wPCA, x = 'Algorhythm', y = 'Accuracy Score', kind = 'box')
plt.xticks(rotation=90)
plt.show()

# --- 2] With PCA: n_components vs Accuracy Score ---

fig, ax = plt.subplots(figsize=(15,8))
sns.pointplot(data = df_wPCA, y = 'Accuracy Score', x = 'n_components', hue = 'Algorhythm', ax = ax)
plt.xticks(rotation=90)
plt.show()

# --- 3] With PCA: computation vs Accurcay Score ---
fig, ax = plt.subplots(figsize=(15,8))
sns.scatterplot(data = df_wPCA, y = 'Accuracy Score', x = 'Computation Time', hue = 'Algorhythm', ax = ax)
plt.xticks(rotation=90)
plt.show()

# --- 4] Without PCA: Algorhythm vs Accuracy Score ---
sns.catplot(data = df_woPCA, x = 'Algorhythm', y = 'Accuracy Score', kind = 'box')
plt.xticks(rotation=90)
plt.show()

# --- 5] Without PCA: computation vs Accurcay Score ---
fig, ax = plt.subplots(figsize=(15,8))
sns.scatterplot(data = df_woPCA, y = 'Accuracy Score', x = 'Computation Time', hue = 'Algorhythm', ax = ax)
plt.xticks(rotation=90)
plt.show()

И теперь мы, наконец, тренируем CNN!

# importing necessary libraries and functions 
import tensorflow as tf
from tensorflow import keras
from keras import layers
from keras.utils import to_categorical
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D, Flatten, Dense
from sklearn.model_selection import train_test_split
import numpy as np
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D, Flatten, Dense

# Importing the target data
with open('/media/hpc-lavasa/Data/krish21112016/abc/exercise_target.txt', 'r') as f:
    target_data = f.readlines()

target = []
for i in range(len(target_data)):
    target.append(int(target_data[i][0]))

# Load the dataset
data = pd.read_csv("/media/hpc-lavasa/Data/krish21112016/abc/exercise_data.csv", header=None)

# Separate the target variable from the input features
X = data.values.reshape(-1, 300, 300, 1)
y = np.array(target)

# Split the data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Define the CNN architecture
model = Sequential()
model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(300, 300, 1)))
model.add(MaxPooling2D((2, 2)))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D((2, 2)))
model.add(Conv2D(128, (3, 3), activation='relu'))
model.add(MaxPooling2D((2, 2)))
model.add(Conv2D(128, (3, 3), activation='relu'))
model.add(MaxPooling2D((2, 2)))
model.add(Flatten())
model.add(Dense(512, activation='relu'))
model.add(Dense(1, activation='sigmoid'))

# Compile the model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

# Train the model
model.fit(X_train, y_train, epochs=10, batch_size=32, validation_data=(X_test, y_test))

# Evaluate the model on the test set
loss, accuracy = model.evaluate(X_test, y_test, verbose=0)
print('Test loss:', loss)
print('Test accuracy:', accuracy) 

/// Вы дошли до конца ///