Lstm modelimin doğruğu 0.99 ama grafikleri çok dalgalı nedeni nedir

# -*- coding: utf-8 -*-

# 📦 GEREKLİ KÜTÜPHANELER
# Uninstalling all relevant libraries to ensure a clean state
!pip uninstall -y numpy mediapipe opencv-python tensorflow pandas

# Installing all necessary libraries together
# This helps pip resolve compatible versions
!pip install numpy mediapipe opencv-python tensorflow pandas

import kagglehub

# Download latest version
path = kagglehub.dataset_download("nandwalritik/yoga-pose-videos-dataset")

print("Path to dataset files:", path)

import os
import shutil
import re

def group_videos_by_pose(source_folder, destination_folder):

    if not os.path.exists(source_folder):
        print(f"Hata: Kaynak klasör '{source_folder}' bulunamadı.")
        return

    # Hedef klasörü oluştur (varsa geç)
    if not os.path.exists(destination_folder):
        os.makedirs(destination_folder)
        print(f"Hedef klasör oluşturuldu: {destination_folder}")

    print(f"'{source_folder}' içindeki videolar pozlara göre gruplanıyor...")

    # Kaynak klasördeki tüm dosyaları listele
    for item_name in os.listdir(source_folder):
        item_path = os.path.join(source_folder, item_name)

        # Sadece video dosyalarını işle
        if os.path.isfile(item_path) and item_name.lower().endswith(".mp4"):
            # Dosya adından poz adını çıkar
            # İsim ve poz adının alt çizgi ile ayrıldığını varsayıyoruz.
            # Bu regex, dosya adındaki son alt çizgiden sonraki kısmı (uzantı hariç) alır.
            match = re.search(r'_([^_]+)\.mp4$', item_name, re.IGNORECASE)
            if match:
                pose_name = match.group(1)

                # Poz adını kullanarak hedef alt klasör yolunu oluştur
                destination_pose_folder = os.path.join(destination_folder, pose_name)

                # Hedef alt klasörü oluştur (varsa geç)
                if not os.path.exists(destination_pose_folder):
                    os.makedirs(destination_pose_folder)
                    print(f"Poz klasörü oluşturuldu/var: {pose_name}/")

                # Dosyayı hedef poz klasörüne kopyala
                destination_file_path = os.path.join(destination_pose_folder, item_name)
                try:
                    shutil.copy2(item_path, destination_file_path) # Metadataları da kopyalar
                    print(f"  '{item_name}' -> '{pose_name}/'")
                except Exception as e:
                    print(f"  '{item_name}' dosyası kopyalanırken bir hata oluştu: {e}")
            else:
                print(f"  '{item_name}' dosyasından poz adı çıkarılamadı, işlenmedi.")
        elif os.path.isdir(item_path):
            print(f"  '{item_name}/' bir klasör, atlanıyor.")
        else:
            print(f"  '{item_name}' bir video dosyası değil veya uzantısı farklı, atlanıyor.")

    print("Pozlara göre gruplama işlemi tamamlandı.")


# Kullanım örneği:
# Kaynak klasör, zip'ten çıkarılan 'Yoga_Vid_Collected' klasörünün yolu olacaktır.
# Bu yol, zip'i nereye çıkardığınıza bağlı olacaktır.
# Not defterinizdeki 'exracted_video_dataset' değişkeni bu yapıya uygun olabilir.
# Tam yolu doğrulamanız gerekebilir. Örnek: /content/exracted_dataset/Yoga_Vid_Collected
kaynak_klasor_yolu = os.path.join(path, "Yoga_Vid_Collected") # exracted_video_dataset değişkeninizin içeriğini kontrol edin
hedef_klasor_yolu = "/content/grouped_yoga_videos" # Yeni oluşturulacak hedef klasör yolu

group_videos_by_pose(kaynak_klasor_yolu, hedef_klasor_yolu)

# Oluşturulan yapıyı görmek için klasör ağacını yazdırabilirsiniz:

# === 0. Kurulumlar ve İçe Aktarmalar ===
import os
import shutil
import zipfile
import csv
import re
import cv2
import numpy as np
#import mediapipe as mp
from google.colab import drive

# === 1. Zip Dosyasını Çıkarma ===
pose_name = "Yoga_Vid_Collected"
video_folder_path = f"/content/drive/MyDrive/dataset2/{pose_name}.zip"
extracted_video_dataset = "/content/grouped_yoga_videos"
extracted_csv_dataset = "/content/extracted_csv_dataset"
drive_hedef_yolu = "MyDrive/Csv_Dataset_Mediapipe"
zip_adı = pose_name

# === 3. MediaPipe ile Keypoint Çıkarımı ===
mp_pose = mp.solutions.pose
pose_model = mp_pose.Pose(static_image_mode=False, min_detection_confidence=0.5)

def extract_mediapipe_keypoints(frame):
    image_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    results = pose_model.process(image_rgb)

    if not results.pose_landmarks:
        return None

    keypoints = []
    for lm in results.pose_landmarks.landmark:
        keypoints.extend([lm.x, lm.y, lm.visibility])
    return keypoints  # 33*3 = 99 değer

# === 4. Tek Bir Videoyu CSV'ye Dönüştürme ===
def video_to_csv_mediapipe(video_path, csv_path):
    cap = cv2.VideoCapture(video_path)
    frame_index = 0
    fps = cap.get(cv2.CAP_PROP_FPS)

    with open(csv_path, mode="w", newline="", encoding="utf-8") as csv_file:
        fieldnames = ["timestamp_sec"] + [f"{coord}{i}" for i in range(1, 34) for coord in ['x', 'y', 'v']]
        writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
        writer.writeheader()

        while True:
            ret, frame = cap.read()
            if not ret:
                break
            timestamp = frame_index / fps
            keypoints = extract_mediapipe_keypoints(frame)
            if keypoints is None:
                frame_index += 1
                continue
            row = {"timestamp_sec": round(timestamp, 2)}
            for i, val in enumerate(keypoints):
                row[fieldnames[i + 1]] = val
            writer.writerow(row)
            frame_index += 1

    cap.release()
    print(f"✅ CSV oluşturuldu: {csv_path}")

# === 5. Tüm Videoları İşleme ===
def is_video_file(filename):
    return filename.lower().endswith(".mp4")

def process_all_videos_mediapipe(root_path):
    for folder in os.listdir(root_path):
        folder_path = os.path.join(root_path, folder)
        if not os.path.isdir(folder_path):
            continue
        for video_file in os.listdir(folder_path):
            if is_video_file(video_file):
                video_path = os.path.join(folder_path, video_file)
                video_id = os.path.splitext(video_file)[0]
                csv_path = os.path.join(folder_path, f"{video_id}.csv")
                print(f"📹 İşleniyor: {video_file}")
                video_to_csv_mediapipe(video_path, csv_path)

process_all_videos_mediapipe(extracted_video_dataset)

# === 6. CSV Dosyalarını csv/ Alt Klasörüne Taşı ===
def csv_dosyalarini_tasi(kok_klasor):
    for yoga_klasoru in os.listdir(kok_klasor):
        klasor_yolu = os.path.join(kok_klasor, yoga_klasoru)
        if not os.path.isdir(klasor_yolu):
            continue
        csv_klasoru_yolu = os.path.join(klasor_yolu, "csv")
        os.makedirs(csv_klasoru_yolu, exist_ok=True)
        for dosya in os.listdir(klasor_yolu):
            if dosya.endswith(".csv"):
                shutil.move(os.path.join(klasor_yolu, dosya), os.path.join(csv_klasoru_yolu, dosya))

csv_dosyalarini_tasi(extracted_video_dataset)

# === 7. CSV'leri Üst Klasöre Kopyala ===
def csv_dosyalarini_ust_klasore_kopyala(kaynak_ana_klasor, hedef_ana_klasor):
    if not os.path.exists(hedef_ana_klasor):
        os.makedirs(hedef_ana_klasor)
    for pose_klasor_adi in os.listdir(kaynak_ana_klasor):
        pose_klasor_yolu = os.path.join(kaynak_ana_klasor, pose_klasor_adi)
        csv_alt_klasor = os.path.join(pose_klasor_yolu, "csv")
        if os.path.isdir(csv_alt_klasor):
            hedef_pose_klasor = os.path.join(hedef_ana_klasor, pose_klasor_adi)
            os.makedirs(hedef_pose_klasor, exist_ok=True)
            for dosya in os.listdir(csv_alt_klasor):
                if dosya.endswith(".csv"):
                    shutil.copy2(os.path.join(csv_alt_klasor, dosya), os.path.join(hedef_pose_klasor, dosya))

csv_dosyalarini_ust_klasore_kopyala(extracted_video_dataset, extracted_csv_dataset)

# -*- coding: utf-8 -*-
"""TezWoA01_ExtractCsv_Mediapipe.ipynb"""

# === 8. ZIP ve Google Drive'a Kaydet ===
def klasoru_zipla_ve_drivea_kaydet(klasor_yolu, zip_dosya_adi, drive_hedef_yolu):
    zip_path = f"/content/{zip_dosya_adi}.zip"
    shutil.make_archive(zip_path.replace(".zip", ""), 'zip', klasor_yolu)

    drive.mount('/content/drive')
    drive_hedef_klasor_yolu = os.path.join("/content/drive", drive_hedef_yolu)
    os.makedirs(drive_hedef_klasor_yolu, exist_ok=True)
    shutil.move(zip_path, os.path.join(drive_hedef_klasor_yolu, os.path.basename(zip_path)))
    print("✅ ZIP dosyası Drive'a yüklendi.")

klasoru_zipla_ve_drivea_kaydet(extracted_csv_dataset, zip_adı, drive_hedef_yolu)

import zipfile
import os
zip_file_name="Yoga_Vid_Collected"
extract_folder = f"/content/unzipped-dataset-csv-{zip_file_name}"  # Çıkarılacak klasör
dataset_zip_path=f"/content/drive/MyDrive/Csv_Dataset_Mediapipe/{zip_file_name}.zip"
# Check if the file exists
if not os.path.exists(dataset_zip_path):
    raise FileNotFoundError(f"The file {dataset_zip_path} does not exist. Please check the path and try again.")

# Check if the file is a valid zip file
try:
    with zipfile.ZipFile(dataset_zip_path, 'r') as zip_ref:
        # If it's a valid zip file, extract it
        zip_ref.extractall(extract_folder)
        print("Çıkarma işlemi tamamlandı.")
except zipfile.BadZipFile:
    # If it's not a valid zip file, raise an error
    raise zipfile.BadZipFile(f"The file {dataset_zip_path} is not a valid zip file. It may be corrupted or have a different format.")

# -*- coding: utf-8 -*-
"""TezWoA02_TrainModel_MediaPipe.ipynb"""

# === 1. Kütüphaneler ve Yardımcı Fonksiyonlar ===
import os
import zipfile
from shutil import rmtree
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split



extract_csv_dataset = "/content/dataset"



# === 3. Dataset Hazırlığı ===
def load_sequences_mediapipe(base_path, test_size=0.40, window_size=50, step=10):
    person_data = {}
    label_map = {}
    current_label = 0

    for pose_folder in sorted(os.listdir(base_path)):
        pose_path = os.path.join(base_path, pose_folder)
        if not os.path.isdir(pose_path): continue

        if pose_folder not in label_map:
            label_map[pose_folder] = current_label
            current_label += 1

        for file in os.listdir(pose_path):
            if not file.endswith(".csv") or file.endswith("_genelEvre.csv"):
                continue
            person_name = file.split("_")[0]
            csv_path = os.path.join(pose_path, file)
            person_data.setdefault(person_name, []).append((pose_folder, csv_path))

    train_people, test_people = train_test_split(sorted(person_data), test_size=test_size, random_state=42)
    def augment_sequence(window, noise_std=0.005, time_shift_max=3):
        # Gaussian noise
        noise = np.random.normal(0, noise_std, window.shape)
        window_noisy = window + noise

        # Time shifting
        shift = np.random.randint(-time_shift_max, time_shift_max+1)
        if shift > 0:
            window_shifted = np.pad(window_noisy, ((shift, 0), (0, 0)), mode='edge')[:-shift]
        elif shift < 0:
            window_shifted = np.pad(window_noisy, ((0, -shift), (0, 0)), mode='edge')[-shift:]
        else:
            window_shifted = window_noisy

        return window_shifted.astype(np.float32)

    def spatial_scaling(window, scale_range=(0.9, 1.1)):
        scale = np.random.uniform(*scale_range)
        return (window * scale).astype(np.float32)

    def mirror_pose(window):
        # x-koordinatlarını 1 - x ile aynala (normalize edilmiş kabul edilir)
        flipped = window.copy()
        flipped[:, ::2] = 1.0 - flipped[:, ::2]
        return flipped.astype(np.float32)


    def create_dataset(people, augment=False):
        X, y = [], []
        coord_columns = [f"{axis}{i}" for i in range(1, 34) for axis in ['x', 'y']]
        for person in people:
            for pose_label, csv_file in person_data[person]:
                df = pd.read_csv(csv_file)
                if not set(coord_columns).issubset(df.columns): continue
                features = df[coord_columns].to_numpy(dtype=np.float32)
                if np.isnan(features).any() or np.isinf(features).any(): continue

                for start in range(0, features.shape[0] - window_size + 1, step):
                    window = features[start:start+window_size]
                    if window.shape[0] == window_size:
                        X.append(window)
                        y.append(label_map[pose_label])



                        """X.append(spatial_scaling(window))
                        y.append(label_map[pose_label])"""

                        X.append(mirror_pose(window))
                        y.append(label_map[pose_label])

                        if augment:  # Artırımlı örnek ekleniyor
                            aug_window = augment_sequence(window)
                            X.append(aug_window)
                            y.append(label_map[pose_label])
        return np.array(X), np.array(y)


    X_train, y_train = create_dataset(train_people, augment=True)
    X_test, y_test = create_dataset(test_people, augment=False)

    return X_train, X_test, y_train, y_test, label_map

X_train, X_test, y_train, y_test, label_map = load_sequences_mediapipe(extract_csv_dataset)
print("Eğitim verisi:", X_train.shape)
print("Test verisi:", X_test.shape)

# === 4. PyTorch Dataset ve DataLoader ===
import torch
from torch.utils.data import Dataset, DataLoader

class PoseSequenceDataset(torch.utils.data.Dataset):
    def __init__(self, X, y):
        self.X = torch.tensor(X, dtype=torch.float32)
        self.y = torch.tensor(y, dtype=torch.long)
    def __len__(self): return len(self.X)
    def __getitem__(self, idx): return self.X[idx], self.y[idx]

train_dataset = PoseSequenceDataset(X_train, y_train)
test_dataset = PoseSequenceDataset(X_test, y_test)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)

# === 5. LSTM Modeli ===
import torch.nn as nn



import torch
import torch.nn as nn

class CNNPerFrame(nn.Module):
    def __init__(self, input_channels=66, cnn_out_channels=32, kernel_size=3, dropout=0.2):
        super(CNNPerFrame, self).__init__()
        self.conv1 = nn.Conv1d(in_channels=2, out_channels=cnn_out_channels, kernel_size=kernel_size, padding=kernel_size//2)
        self.relu = nn.ReLU()
        self.bn = nn.BatchNorm1d(cnn_out_channels)
        self.dropout = nn.Dropout(dropout)

    def forward(self, x):
        x = x.view(-1, 33, 2).permute(0, 2, 1)      # (B, 2, 33)
        x = self.conv1(x)                           # (B, cnn_out, 33)
        x = self.relu(x)
        x = self.bn(x)
        x = self.dropout(x)
        return x.view(x.size(0), -1)                # (B, cnn_out * 33)

class CNNLSTM_YogaModel(nn.Module):
    def __init__(self, frame_cnn_out=32*33, lstm_hidden_size=128, num_classes=6):
        super().__init__()
        self.cnn_per_frame = CNNPerFrame()
        self.lstm = nn.LSTM(input_size=frame_cnn_out,
                            hidden_size=lstm_hidden_size,
                            num_layers=1,
                            batch_first=True,
                            bidirectional=True)
        self.fc = nn.Linear(lstm_hidden_size * 2, num_classes)

    def forward(self, x):
        B, T, C = x.size()                          # (B, 50, 66)
        x = x.view(B * T, C)                        # (B*T, 66)
        cnn_features = self.cnn_per_frame(x)        # (B*T, F)
        cnn_features = cnn_features.view(B, T, -1)  # (B, T, F)
        lstm_out, _ = self.lstm(cnn_features)       # (B, T, 2*H)
        out = self.fc(lstm_out[:, -1, :])           # (B, num_classes)
        return out



# === 6. Eğitim Hazırlığı ===
from sklearn.utils.class_weight import compute_class_weight
from sklearn.metrics import accuracy_score, f1_score
import torch.nn.functional as F

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
class_weights = compute_class_weight(class_weight='balanced', classes=np.unique(y_train), y=y_train)
class_weights_tensor = torch.tensor(class_weights, dtype=torch.float32).to(device)

#model = PoseLSTMClassifier(input_size=66, num_classes=len(label_map)).to(device)


model = CNNLSTM_YogaModel(
    frame_cnn_out=32*33,       # CNN çıkış boyutu (cnn_out_channels * keypoint sayısı)
    lstm_hidden_size=128,      # LSTM gizli katman boyutu
    num_classes=6              # Yoga pozu sayısı
).to(device)

criterion = nn.CrossEntropyLoss(weight=class_weights_tensor)
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

# === 7. Eğitim Döngüsü ===
num_epochs = 75
patience = 10
best_val_loss = float('inf')
epochs_no_improve = 0
early_stop = False

train_losses, val_losses = [], []
train_accuracies, val_accuracies, val_f1_scores = [], [], []

for epoch in range(num_epochs):
    if early_stop: break
    model.train()
    train_loss = 0
    train_preds, train_labels = [], []

    for inputs, labels in train_loader:
        inputs, labels = inputs.to(device), labels.to(device)
        outputs = model(inputs)
        loss = criterion(outputs, labels)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        train_loss += loss.item()
        preds = torch.argmax(outputs, dim=1)
        train_preds.extend(preds.cpu().numpy())
        train_labels.extend(labels.cpu().numpy())

    train_acc = accuracy_score(train_labels, train_preds)

    # Doğrulama
    model.eval()
    val_loss = 0
    val_preds, val_labels = [], []

    with torch.no_grad():
        for inputs, labels in test_loader:
            inputs, labels = inputs.to(device), labels.to(device)
            outputs = model(inputs)
            loss = criterion(outputs, labels)
            val_loss += loss.item()
            preds = torch.argmax(outputs, dim=1)
            val_preds.extend(preds.cpu().numpy())
            val_labels.extend(labels.cpu().numpy())

    val_acc = accuracy_score(val_labels, val_preds)
    val_f1 = f1_score(val_labels, val_preds, average='weighted')

    # Kayıt
    train_losses.append(train_loss / len(train_loader))
    val_losses.append(val_loss / len(test_loader))
    train_accuracies.append(train_acc)
    val_accuracies.append(val_acc)
    val_f1_scores.append(val_f1)

    if val_loss < best_val_loss:
        best_val_loss = val_loss
        epochs_no_improve = 0
        torch.save(model.state_dict(), "best_model.pt")
    else:
        epochs_no_improve += 1
        if epochs_no_improve >= patience:
            early_stop = True

    print(f"Epoch {epoch+1}/{num_epochs} - loss: {train_losses[-1]:.4f} - acc: {train_acc:.4f} - val_loss: {val_losses[-1]:.4f} - val_acc: {val_acc:.4f} - val_f1: {val_f1:.4f}")

# === 8. Sonuç ve Model Kaydı ===
from sklearn.metrics import classification_report

model.eval()
all_preds, all_labels = [], []

with torch.no_grad():
    for inputs, labels in test_loader:
        inputs = inputs.to(device)
        outputs = model(inputs)
        preds = torch.argmax(outputs, dim=1).cpu().numpy()
        all_preds.extend(preds)
        all_labels.extend(labels.numpy())

print("Test Doğruluğu:", accuracy_score(all_labels, all_preds))
print(classification_report(all_labels, all_preds, target_names=label_map.keys()))

# Model kaydı
torch.save(model.state_dict(), "pose_lstm_model.pt")
print("✅ Model başarıyla kaydedildi.")

import matplotlib.pyplot as plt

epochs = range(1, len(train_losses) + 1)

plt.figure(figsize=(14, 5))

# --- LOSS GRAFİĞİ ---
plt.subplot(1, 2, 1)
plt.plot(epochs, train_losses, label="Train Loss")
plt.plot(epochs, val_losses, label="Validation Loss")
plt.xlabel("Epoch")
plt.ylabel("Loss")
plt.title("Loss Grafiği")
plt.legend()
plt.grid(True)

# --- ACCURACY GRAFİĞİ ---
plt.subplot(1, 2, 2)
plt.plot(epochs, train_accuracies, label="Train Accuracy")
plt.plot(epochs, val_accuracies, label="Validation Accuracy")
plt.xlabel("Epoch")
plt.ylabel("Accuracy")
plt.title("Accuracy Grafiği")
plt.legend()
plt.grid(True)

plt.tight_layout()
plt.show()

import matplotlib.pyplot as plt

epochs = range(1, len(train_losses) + 1)

plt.figure(figsize=(14, 5))

# --- LOSS GRAFİĞİ ---
plt.subplot(1, 2, 1)
plt.plot(epochs, train_losses, label="Train Loss")
plt.plot(epochs, val_losses, label="Validation Loss")
plt.xlabel("Epoch")
plt.ylabel("Loss")
plt.title("Loss Grafiği")
plt.legend()
plt.grid(True)
plt.xlim(1, 10)
plt.ylim(1, 10)  # LOSS için y aralığı

# --- ACCURACY GRAFİĞİ ---
plt.subplot(1, 2, 2)
plt.plot(epochs, train_accuracies, label="Train Accuracy")
plt.plot(epochs, val_accuracies, label="Validation Accuracy")
plt.xlabel("Epoch")
plt.ylabel("Accuracy")
plt.title("Accuracy Grafiği")
plt.legend()
plt.grid(True)
plt.xlim(0, 30)
plt.ylim(0, 1)  # ACCURACY için y aralığı

plt.tight_layout()
plt.show()

from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay

# Confusion matrix hesapla
cm = confusion_matrix(all_labels, all_preds)

# Etiket isimleri
class_names = list(label_map.keys())

# Görselleştir
disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=class_names)
fig, ax = plt.subplots(figsize=(10, 10))
disp.plot(ax=ax, cmap=plt.cm.Blues, xticks_rotation=45)
plt.title("Confusion Matrix")
plt.grid(False)
plt.show()

burada başından sonuna kadar kullandığım kodlarım var mediapipe ile keypoint verilerini csv dosyalarına kaydedip bu dosyalar ile modelimi eğitmeye çalışıyorum

Test Doğruluğu: 0.9959153051017006
              precision    recall  f1-score   support

Bhujangasana       1.00      0.99      1.00      2108
   Padmasana       1.00      1.00      1.00      2074
   Shavasana       0.99      1.00      1.00      1846
    Tadasana       0.99      0.99      0.99      2000
 Trikonasana       1.00      1.00      1.00      1866
 Vrikshasana       0.99      0.99      0.99      2102

    accuracy                           1.00     11996
   macro avg       1.00      1.00      1.00     11996
weighted avg       1.00      1.00      1.00     11996

ilgili etiketlerimin doğruluk oranları bu şekilde çıkıyor bu değerler normal mi ya da ner hata yapıyorum çözemedim

Overfitting var gibi. Öğrenme katsayısını düşürüp veya optimizasyon algoritmasını değiştirip tekrar deneseniz?