{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":39763,"databundleVersionId":11756775,"sourceType":"competition"},{"sourceId":11367935,"sourceType":"datasetVersion","datasetId":7116013},{"sourceId":11368083,"sourceType":"datasetVersion","datasetId":7116134},{"sourceId":11368169,"sourceType":"datasetVersion","datasetId":7116196},{"sourceId":11368268,"sourceType":"datasetVersion","datasetId":7116272},{"sourceId":11368499,"sourceType":"datasetVersion","datasetId":7116445},{"sourceId":11368545,"sourceType":"datasetVersion","datasetId":7116479},{"sourceId":11368547,"sourceType":"datasetVersion","datasetId":7116481},{"sourceId":11376433,"sourceType":"datasetVersion","datasetId":7122462},{"sourceId":11376448,"sourceType":"datasetVersion","datasetId":7122476},{"sourceId":11376464,"sourceType":"datasetVersion","datasetId":7122489},{"sourceId":11376742,"sourceType":"datasetVersion","datasetId":7122712},{"sourceId":11376868,"sourceType":"datasetVersion","datasetId":7122812},{"sourceId":11376871,"sourceType":"datasetVersion","datasetId":7122814},{"sourceId":11376872,"sourceType":"datasetVersion","datasetId":7122815},{"sourceId":11376935,"sourceType":"datasetVersion","datasetId":7122866},{"sourceId":11377083,"sourceType":"datasetVersion","datasetId":7122981},{"sourceId":11377231,"sourceType":"datasetVersion","datasetId":7123090},{"sourceId":11377291,"sourceType":"datasetVersion","datasetId":7123138},{"sourceId":11377325,"sourceType":"datasetVersion","datasetId":7123163},{"sourceId":11377334,"sourceType":"datasetVersion","datasetId":7123172},{"sourceId":11377594,"sourceType":"datasetVersion","datasetId":7123380},{"sourceId":11377614,"sourceType":"datasetVersion","datasetId":7123394},{"sourceId":11377741,"sourceType":"datasetVersion","datasetId":7123490},{"sourceId":11377752,"sourceType":"datasetVersion","datasetId":7123499},{"sourceId":11377756,"sourceType":"datasetVersion","datasetId":7123503},{"sourceId":11377935,"sourceType":"datasetVersion","datasetId":7123649},{"sourceId":11377970,"sourceType":"datasetVersion","datasetId":7123675},{"sourceId":11378141,"sourceType":"datasetVersion","datasetId":7123813},{"sourceId":11378162,"sourceType":"datasetVersion","datasetId":7123831},{"sourceId":11378178,"sourceType":"datasetVersion","datasetId":7123842}],"dockerImageVersionId":31011,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Yale/UNC-CH Geophysical Waveform Inversion: Artık Bağlantılarla Güçlendirilmiş UNet Modeli\n\n## Giriş\n\nYale Üniversitesi ve Kuzey Carolina Üniversitesi Chapel Hill (UNC-CH) tarafından düzenlenen **Geophysical Waveform Inversion** Kaggle yarışması, tam dalga biçimi ters çevirme (Full Waveform Inversion - FWI) problemini çözmek için fizik tabanlı makine öğrenimi modelleri geliştirmeyi amaçlamaktadır. FWI, sismik dalga verilerinden yeraltı hız haritalarını tahmin ederek enerji keşfi, karbon depolama, tıbbi ultrason ve malzeme testi gibi alanlarda kritik bir rol oynar. Geleneksel fizik tabanlı yöntemler yavaş ve gürültülü verilerde hatalı olabilirken, saf makine öğrenimi modelleri genelleştirme sorunları yaşar. Bu yarışma, fizik bilgisi ile makine öğrenimini birleştiren yenilikçi yaklaşımlar geliştirerek bu sınırlamaları aşmayı hedefler.\n\nBu not defteri, OpenFWI veri seti üzerinde artık bağlantılarla güçlendirilmiş bir UNet modeli kullanarak FWI problemini çözmek için geliştirilmiş bir çözümü sunar. Çözüm, [5 Depth U-Net with Residual](https://www.kaggle.com/code/adhok93/5-depth-u-net-with-residual) ve [OpenFWI InversionNet Train with 670G Datasets](https://www.kaggle.com/code/seshurajup/openfwi-inversionnet-train-with-670g-datasets) not defterlerinden esinlenmiştir. Kod, tekrarlanabilirlik, modülerlik ve yüksek performans için optimize edilmiştir. Bu doküman, hem yeni başlayanlar hem de deneyimli veri bilimciler için eğitici bir rehber olarak tasarlanmıştır.\n\nKaynak: [[GWI] Improved UNet pipepline with larger dataset\n](https://www.kaggle.com/code/egortrushin/gwi-improved-unet-pipepline-with-larger-dataset)\n\n## Yarışma Özeti\n\n- **Görev**: 3D sismik dalga verilerinden 2D yeraltı hız haritalarını tahmin etmek.\n- **Veri Seti**: OpenFWI veri setinden türetilmiş Vel, Fault ve Style aileleri.\n- **Değerlendirme Metriği**: Ortalama Mutlak Hata (Mean Absolute Error - MAE).\n- **Gönderim Formatı**: Her `oid` için yalnızca tek sayılı sütunlar (`x_1, x_3, ..., x_69`) içeren 2D hız haritaları.\n- **Son Teslim Tarihi**: 30 Haziran 2025.\n- **Ödüller**: Toplam 50.000 USD (1. sıra: 12.000 USD).\n\n## İçerik\n\n1. [Veri Seti ve Ön İşleme](#1-veri-seti-ve-ön-işleme)\n2. [Model Mimarisi: UNet](#2-model-mimarisi-unet)\n3. [Eğitim ve Doğrulama Süreci](#3-eğitim-ve-doğrulama-süreci)\n4. [Tahmin ve Gönderim](#4-tahmin-ve-gönderim)\n5. [Sonuçlar ve İyileştirme Önerileri](#5-sonuçlar-ve-iyileştirme-önerileri)\n6. [Kaggle Türkiye Topluluğuna Katkı](#6-kaggle-topluluğuna-katkı)","metadata":{"_uuid":"02d4fb39-8827-4470-8966-bf1d03af12a8","_cell_guid":"8de7f4e4-2e3f-43c5-b1c1-eb6ba26b14c1","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-04-25T14:53:18.823205Z","iopub.execute_input":"2025-04-25T14:53:18.823481Z","iopub.status.idle":"2025-04-25T14:53:23.506381Z","shell.execute_reply.started":"2025-04-25T14:53:18.823463Z","shell.execute_reply":"2025-04-25T14:53:23.505626Z"},"jupyter":{"outputs_hidden":false}}},{"cell_type":"code","source":"# Gerekli kütüphaneleri içe aktar\nimport os\nimport sys\nimport yaml\nimport csv\nimport time\nimport datetime\nimport random\nimport numpy as np\nfrom pathlib import Path\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.data import Dataset, DataLoader\nfrom pprint import pprint","metadata":{"_uuid":"3d6cb614-d6bd-4e9b-bab9-79f771a4b3ac","_cell_guid":"a772f8b7-472c-4da4-b3ba-c8b3af9fe3d2","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-04-25T23:15:33.665205Z","iopub.execute_input":"2025-04-25T23:15:33.665382Z","iopub.status.idle":"2025-04-25T23:15:35.494463Z","shell.execute_reply.started":"2025-04-25T23:15:33.665365Z","shell.execute_reply":"2025-04-25T23:15:35.493898Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 1. Veri Seti ve Ön İşleme\n\nOpenFWI veri seti, sismik dalga kayıtları ve karşılık gelen hız haritalarından oluşur. Veri seti, Vel, Fault ve Style ailelerini içerir ve her biri 500 örnek içeren `.npy` dosyaları şeklinde organize edilmiştir. Sismik veriler 4D diziler (`batch_size, num_sources, time_steps, num_receivers`) olarak, hız haritaları ise 3D diziler (`batch_size, height, width`) olarak temsil edilir.\n\n### Veri Yapısı\n- **Eğitim Verileri**:\n  - Sismik veriler: `data/*.npy` veya `seis_{n}_1_{i}.npy`.\n  - Hız haritaları: `model/*.npy` veya `vel_{n}_1_{i}.npy`.\n  - Örnek dosya çifti: `data1.npy` ve `model1.npy`.\n- **Test Verileri**:\n  - Sismik veriler: `test/{oid}.npy`.\n  - Tahmin edilmesi gereken: 2D hız haritaları.\n\n### Ön İşleme\nVeri yükleme, `SeismicDataset` ve `TestDataset` sınıflarıyla gerçekleştirilir. Veriler, bellek verimliliği için `mmap_mode='r'` kullanılarak yüklenir. Eğitim ve doğrulama setleri, `valid_frac` ve `train_frac` parametreleriyle ayrılır.","metadata":{"_uuid":"837c296a-7310-418c-9d82-3c5535342734","_cell_guid":"7d974416-b9bb-443a-bd2f-1fc5f7563297","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-04-25T16:01:28.767697Z","iopub.execute_input":"2025-04-25T16:01:28.768091Z","iopub.status.idle":"2025-04-25T16:01:33.324282Z","shell.execute_reply.started":"2025-04-25T16:01:28.768062Z","shell.execute_reply":"2025-04-25T16:01:33.32348Z"},"jupyter":{"outputs_hidden":false}}},{"cell_type":"code","source":"# Veri seti için yardımcı fonksiyonlar\ndef inputs_files_to_output_files(input_files):\n    \"\"\"\n    Sismik veri dosyalarından hız haritası dosyalarına geçiş yapar.\n    Örneğin, 'seis' -> 'vel', 'data' -> 'model'.\n    \"\"\"\n    return [Path(str(f).replace('seis', 'vel').replace('data', 'model')) for f in input_files]\n\ndef get_train_files(data_path):\n    \"\"\"\n    Tüm giriş ve çıkış dosyalarını toplar ve eşleşmelerini doğrular.\n    \"\"\"\n    all_inputs = [f for f in Path(data_path).rglob('*.npy') if ('seis' in f.stem) or ('data' in f.stem)]\n    all_outputs = inputs_files_to_output_files(all_inputs)\n    assert all(f.exists() for f in all_outputs)\n    return all_inputs, all_outputs\n\n# Eğitim ve doğrulama veri sınıfı\nclass SeismicDataset(Dataset):\n    \"\"\"\n    Sismik veri ve hız haritalarını yükler. Her dosya 500 örnek içerir.\n    \"\"\"\n    def __init__(self, inputs_files, output_files, n_examples_per_file=500):\n        assert len(inputs_files) == len(output_files)\n        self.inputs_files = inputs_files\n        self.output_files = output_files\n        self.n_examples_per_file = n_examples_per_file\n\n    def __len__(self):\n        return len(self.inputs_files) * self.n_examples_per_file\n\n    def __getitem__(self, idx):\n        file_idx = idx // self.n_examples_per_file\n        sample_idx = idx % self.n_examples_per_file\n        X = np.load(self.inputs_files[file_idx], mmap_mode='r')\n        y = np.load(self.output_files[file_idx], mmap_mode='r')\n        try:\n            return X[sample_idx].copy(), y[sample_idx].copy()\n        finally:\n            del X, y\n\n# Test veri sınıfı\nclass TestDataset(Dataset):\n    \"\"\"\n    Test verilerini yükler ve tahmin için hazırlar.\n    \"\"\"\n    def __init__(self, test_files):\n        self.test_files = test_files\n\n    def __len__(self):\n        return len(self.test_files)\n\n    def __getitem__(self, i):\n        test_file = self.test_files[i]\n        return np.load(test_file), test_file.stem","metadata":{"_uuid":"5d1cafc2-9f67-4b88-a3e3-fe36a27d7f4f","_cell_guid":"9f8fed0d-da5a-415a-bad0-10d0dbca5666","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-04-25T23:15:35.495092Z","iopub.execute_input":"2025-04-25T23:15:35.495359Z","iopub.status.idle":"2025-04-25T23:15:35.503485Z","shell.execute_reply.started":"2025-04-25T23:15:35.495342Z","shell.execute_reply":"2025-04-25T23:15:35.502593Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 2. Model Mimarisi: UNet\n\nModel, sismik verilerden hız haritalarını tahmin etmek için artık bağlantılarla güçlendirilmiş bir UNet mimarisi kullanır. UNet, kodlayıcı (encoder) ve çözücü (decoder) yollarından oluşan U şeklindeki yapısıyla, görüntü segmentasyonu ve regresyon görevlerinde yaygın olarak kullanılır.\n\n### UNet Mimarisi\n- **Kodlayıcı**: Özellik sayısını artırır ve uzamsal boyutları maksimum havuzlama ile küçültür.\n- **Darboğaz**: En derin katmanda özellik temsilini sıkıştırır.\n- **Çözücü**: Özellik haritalarını bilinear interpolasyonla büyütür ve kodlayıcıdan gelen atlama bağlantılarıyla birleştirir.\n- **Artık Bağlantılar**: `ResidualDoubleConv` modülü, gradyan akışını iyileştirir ve modelin genelleştirme yeteneğini artırır.","metadata":{"_uuid":"2a1116e2-0be4-4cb7-b64c-3f71cc8bda0f","_cell_guid":"37b5f2bd-ef44-4234-841a-e9d8eec4a89e","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-04-25T16:01:33.346202Z","iopub.execute_input":"2025-04-25T16:01:33.346529Z","iopub.status.idle":"2025-04-25T16:01:33.372034Z","shell.execute_reply.started":"2025-04-25T16:01:33.346501Z","shell.execute_reply":"2025-04-25T16:01:33.371187Z"},"jupyter":{"outputs_hidden":false}}},{"cell_type":"code","source":"# UNet model bileşenleri\nclass ResidualDoubleConv(nn.Module):\n    \"\"\"\n    İki konvolüsyon katmanı ve artık bağlantı içerir.\n    (Conv -> BN -> ReLU) * 2 + Residual Connection\n    \"\"\"\n    def __init__(self, in_channels, out_channels, mid_channels=None):\n        super().__init__()\n        if not mid_channels:\n            mid_channels = out_channels\n        self.conv1 = nn.Conv2d(in_channels, mid_channels, kernel_size=3, padding=1, bias=False)\n        self.bn1 = nn.BatchNorm2d(mid_channels)\n        self.relu = nn.ReLU(inplace=True)\n        self.conv2 = nn.Conv2d(mid_channels, out_channels, kernel_size=3, padding=1, bias=False)\n        self.bn2 = nn.BatchNorm2d(out_channels)\n        if in_channels == out_channels:\n            self.shortcut = nn.Identity()\n        else:\n            self.shortcut = nn.Sequential(\n                nn.Conv2d(in_channels, out_channels, kernel_size=1, bias=False),\n                nn.BatchNorm2d(out_channels)\n            )\n\n    def forward(self, x):\n        identity = x\n        out = self.conv1(x)\n        out = self.bn1(out)\n        out = self.relu(out)\n        out = self.conv2(out)\n        out = self.bn2(out)\n        identity_mapped = self.shortcut(identity)\n        out += identity_mapped\n        out = self.relu(out)\n        return out\n\nclass Up(nn.Module):\n    \"\"\"\n    Üst örnekleme ve ardından artık bağlantılı konvolüsyon.\n    \"\"\"\n    def __init__(self, in_channels, out_channels, bilinear=True):\n        super().__init__()\n        self.bilinear = bilinear\n        if bilinear:\n            self.up = nn.Upsample(scale_factor=2, mode=\"bilinear\", align_corners=False)\n            self.conv = ResidualDoubleConv(in_channels + out_channels, out_channels)\n        else:\n            self.up = nn.ConvTranspose2d(in_channels, in_channels // 2, kernel_size=2, stride=2)\n            conv_in_channels = in_channels // 2\n            skip_channels = out_channels\n            total_in_channels = conv_in_channels + skip_channels\n            self.conv = ResidualDoubleConv(total_in_channels, out_channels)\n\n    def forward(self, x1, x2):\n        x1 = self.up(x1)\n        diffY = x2.size(2) - x1.size(2)\n        diffX = x2.size(3) - x1.size(3)\n        x1 = F.pad(x1, [diffX // 2, diffX - diffX // 2, diffY // 2, diffY - diffY // 2])\n        x = torch.cat([x2, x1], dim=1)\n        return self.conv(x)\n\nclass OutConv(nn.Module):\n    \"\"\"\n    Çıkış için 1x1 konvolüsyon.\n    \"\"\"\n    def __init__(self, in_channels, out_channels):\n        super().__init__()\n        self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=1)\n\n    def forward(self, x):\n        return self.conv(x)\n\nclass UNet(nn.Module):\n    \"\"\"\n    Artık bağlantılarla güçlendirilmiş UNet mimarisi.\n    \"\"\"\n    def __init__(self, n_channels=5, n_classes=1, init_features=32, depth=5, bilinear=True):\n        super().__init__()\n        self.n_channels = n_channels\n        self.n_classes = n_classes\n        self.bilinear = bilinear\n        self.depth = depth\n        self.initial_pool = nn.AvgPool2d(kernel_size=(14, 1), stride=(14, 1))\n        self.inc = ResidualDoubleConv(n_channels, init_features)\n        self.encoder_convs = nn.ModuleList()\n        self.encoder_pools = nn.ModuleList()\n        current_features = init_features\n        for _ in range(depth):\n            conv = ResidualDoubleConv(current_features, current_features * 2)\n            pool = nn.MaxPool2d(2)\n            self.encoder_convs.append(conv)\n            self.encoder_pools.append(pool)\n            current_features *= 2\n        self.bottleneck = ResidualDoubleConv(current_features, current_features)\n        self.decoder_blocks = nn.ModuleList()\n        for _ in range(depth):\n            up_block = Up(current_features, current_features // 2, bilinear)\n            self.decoder_blocks.append(up_block)\n            current_features //= 2\n        self.outc = OutConv(current_features, n_classes)\n\n    def _pad_or_crop(self, x, target_h=70, target_w=70):\n        \"\"\"\n        Girdi tensörünü hedef boyutlara doldurur veya kırpar.\n        \"\"\"\n        _, _, h, w = x.shape\n        if h < target_h:\n            pad_top = (target_h - h) // 2\n            pad_bottom = target_h - h - pad_top\n            x = F.pad(x, (0, 0, pad_top, pad_bottom))\n            h = target_h\n        if w < target_w:\n            pad_left = (target_w - w) // 2\n            pad_right = target_w - w - pad_left\n            x = F.pad(x, (pad_left, pad_right, 0, 0))\n            w = target_w\n        if h > target_h:\n            crop_top = (h - target_h) // 2\n            x = x[:, :, crop_top: crop_top + target_h, :]\n            h = target_h\n        if w > target_w:\n            crop_left = (w - target_w) // 2\n            x = x[:, :, :, crop_left: crop_left + target_w]\n            w = target_w\n        return x\n\n    def forward(self, x):\n        x_pooled = self.initial_pool(x)\n        x_resized = self._pad_or_crop(x_pooled, target_h=70, target_w=70)\n        skip_connections = []\n        xi = x_resized\n        xi = self.inc(xi)\n        skip_connections.append(xi)\n        for i in range(self.depth):\n            xi = self.encoder_convs[i](xi)\n            skip_connections.append(xi)\n            xi = self.encoder_pools[i](xi)\n        xi = self.bottleneck(xi)\n        xu = xi\n        for i, block in enumerate(self.decoder_blocks):\n            skip_index = self.depth - 1 - i\n            skip = skip_connections[skip_index]\n            xu = block(xu, skip)\n        logits = self.outc(xu)\n        output = logits * 1000.0 + 1500.0  # Problem aralığına ölçeklendirme\n        return output","metadata":{"_uuid":"f321f9c2-27b1-4ece-b584-f5c2f8900ea9","_cell_guid":"378974e8-8754-4bd4-a43d-b260cde8bc14","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-04-25T23:15:35.504306Z","iopub.execute_input":"2025-04-25T23:15:35.504569Z","iopub.status.idle":"2025-04-25T23:15:35.527856Z","shell.execute_reply.started":"2025-04-25T23:15:35.504552Z","shell.execute_reply":"2025-04-25T23:15:35.527251Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 3. Eğitim ve Doğrulama Süreci\n\nEğitim süreci, modelin sismik verilerden hız haritalarını öğrenmesini sağlar. AdamW optimizasyonu, L1 kaybı (MAE) ve ReduceLROnPlateau öğrenme oranı planlayıcısı kullanılır. Erken durdurma, doğrulama kaybı iyileşmediğinde devreye girer.\n\n### Konfigürasyon\nEğitim parametreleri, `config.yaml` dosyasında tanımlanır.","metadata":{"_uuid":"ff372a4e-07e5-4763-910f-8f104174729d","_cell_guid":"b2eaa3c3-f354-42c3-93d2-9daac51f5247","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-04-25T22:54:14.955895Z","iopub.execute_input":"2025-04-25T22:54:14.956093Z","iopub.status.idle":"2025-04-25T22:54:14.972146Z","shell.execute_reply.started":"2025-04-25T22:54:14.956077Z","shell.execute_reply":"2025-04-25T22:54:14.971205Z"},"jupyter":{"outputs_hidden":false}}},{"cell_type":"code","source":"# Konfigürasyon dosyasını oluştur\nwith open(\"config.yaml\", \"w\") as f:\n    f.write(\"\"\"\ndata_path: /kaggle/input/waveform-inversion\nmodel: \n    name: UNet\n    unet_params:\n        init_features: 32\n        depth: 5\nread_weights: null\nbatch_size: 64\nprint_freq: 500\nmax_epochs: 20\nes_epochs: 4\nseed: 42\nvalid_frac: 36\ntrain_frac: 5\noptimizer:\n    lr: 0.0001\n    weight_decay: 0.001\nscheduler:\n    params:\n        factor: 0.316227766\n        patience: 1\n\"\"\")\n\n# Yardımcı fonksiyonlar\ndef seed_everything(seed_value: int) -> None:\n    \"\"\"\n    Rastgele tohumları sabitleyerek tekrarlanabilirlik sağlar.\n    \"\"\"\n    random.seed(seed_value)\n    np.random.seed(seed_value)\n    torch.manual_seed(seed_value)\n    if torch.cuda.is_available():\n        torch.cuda.manual_seed(seed_value)\n        torch.cuda.manual_seed_all(seed_value)\n    if torch.backends.cudnn.is_available:\n        torch.backends.cudnn.deterministic = True\n        torch.backends.cudnn.benchmark = False\n\ndef format_time(elapsed):\n    \"\"\"\n    Süreyi hh:mm:ss formatında döndürür.\n    \"\"\"\n    elapsed_rounded = int(round(elapsed))\n    return str(datetime.timedelta(seconds=elapsed_rounded))","metadata":{"_uuid":"752f7918-bf0b-4013-8fc5-ed66eb74f3be","_cell_guid":"1afcf700-dcf4-49ec-bdca-ac2d44c0c5ba","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-04-25T23:15:35.528578Z","iopub.execute_input":"2025-04-25T23:15:35.528823Z","iopub.status.idle":"2025-04-25T23:15:35.555199Z","shell.execute_reply.started":"2025-04-25T23:15:35.528806Z","shell.execute_reply":"2025-04-25T23:15:35.554580Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Eğitim Döngüsü\nEğitim ve doğrulama süreçleri, veri yükleyicileriyle birlikte çalışır.","metadata":{"_uuid":"9b9749ec-5c18-4a26-a4b2-ccebb4a4a7de","_cell_guid":"a38d0eb3-ba33-4c80-916b-b5d70521c24f","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false}}},{"cell_type":"code","source":"# Eğitim ve doğrulama\nprint(f\"GPU: {torch.cuda.get_device_name(0)}\")\n_, total = torch.cuda.mem_get_info(device=0)\nprint(f\"GPU Belleği: {total / 1024**3:.2f}GB\")\n\n# Konfigürasyonu oku\nwith open(\"config.yaml\", \"r\") as file_obj:\n    config = yaml.safe_load(file_obj)\nprint(\"\\nKonfigürasyon Parametreleri:\")\npprint(config)\nif config[\"data_path\"] is None:\n    config[\"data_path\"] = os.environ[\"TMPDIR\"]\n    print(\"data_path:\", config[\"data_path\"])\nprint()\n\n# Rastgele tohumu sabitle\nseed_everything(config[\"seed\"])\n\n# Veri setini yükle\nall_inputs, all_outputs = [], []\nfor i in range(1, 31):\n    all_inputs1, all_outputs1 = get_train_files(config[\"data_path\"] + f\"-{i}\")\n    all_inputs.extend(all_inputs1)\n    all_outputs.extend(all_outputs1)\nprint(\"Toplam giriş/çıkış dosyası sayısı:\", len(all_inputs))\n\n# Eğitim ve doğrulama setlerini ayır\nvalid_inputs = [all_inputs[i] for i in range(0, len(all_inputs), config[\"valid_frac\"])]\ntrain_inputs = [f for f in all_inputs if f not in valid_inputs]\nif config[\"train_frac\"] > 1:\n    train_inputs = [train_inputs[i] for i in range(0, len(train_inputs), config[\"train_frac\"])]\n\nprint(\"Eğitim dosyası sayısı:\", len(train_inputs))\nprint(\"Doğrulama dosyası sayısı:\", len(valid_inputs))\nprint()\n\ntrain_outputs = inputs_files_to_output_files(train_inputs)\nvalid_outputs = inputs_files_to_output_files(valid_inputs)\n\n# Veri yükleyicilerini oluştur\ndstrain = SeismicDataset(train_inputs, train_outputs)\ndltrain = DataLoader(\n    dstrain,\n    batch_size=config[\"batch_size\"],\n    shuffle=True,\n    pin_memory=False,\n    drop_last=True,\n    num_workers=4,\n    persistent_workers=True,\n)\n\ndsvalid = SeismicDataset(valid_inputs, valid_outputs)\ndlvalid = DataLoader(\n    dsvalid,\n    batch_size=4 * config[\"batch_size\"],\n    shuffle=False,\n    pin_memory=False,\n    drop_last=False,\n    num_workers=4,\n    persistent_workers=True,\n)\n\n# Modeli ve cihazı ayarla\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel = UNet(**config[\"model\"][\"unet_params\"]).to(device)\n\n# Önceden eğitilmiş ağırlıkları yükle (varsa)\nif config[\"read_weights\"] is not None:\n    print(\"Ağırlıklar şuradan yükleniyor:\", config[\"read_weights\"])\n    model.load_state_dict(torch.load(config[\"read_weights\"], weights_only=True))\n\n# Optimizasyon ve kayıp\ncriterion = nn.L1Loss()\noptimizer = torch.optim.AdamW(model.parameters(), **config[\"optimizer\"])\nscheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, 'min', **config[\"scheduler\"][\"params\"])\n\n# Eğitim döngüsü\nbest_val_loss = 10000.0\nepochs_wo_improvement = 0\nt0 = time.time()\n\nfor epoch in range(1, config[\"max_epochs\"] + 1):\n    model.train()\n    train_losses = []\n    for step, (inputs, targets) in enumerate(dltrain):\n        inputs = inputs.to(device)\n        targets = targets.to(device)\n        optimizer.zero_grad()\n        with torch.autocast(device_type=\"cuda\"):\n            outputs = model(inputs)\n            loss = criterion(outputs, targets)\n        loss.backward()\n        optimizer.step()\n        train_losses.append(loss.item())\n\n        if step % config[\"print_freq\"] == config[\"print_freq\"] - 1 or step == len(dltrain) - 1:\n            trn_loss = np.mean(train_losses)\n            t1 = format_time(time.time() - t0)\n            free, total = torch.cuda.mem_get_info(device=0)\n            mem_used = (total - free) / 1024**3\n            lr = optimizer.param_groups[-1]['lr']\n            print(\n                f\"Epoch: {epoch:02d}  Adım {step+1}/{len(dltrain)}  Eğitim Kaybı: {trn_loss:.2f}  LR: {lr:.2e}  GPU Kullanımı: {mem_used:.2f}GB  Geçen Süre: {t1}\"\n            )\n\n    model.eval()\n    valid_losses = []\n    for inputs, targets in dlvalid:\n        inputs = inputs.to(device)\n        targets = targets.to(device)\n        with torch.inference_mode():\n            with torch.autocast(device_type=\"cuda\"):\n                outputs = model(inputs)\n        loss = criterion(outputs, targets)\n        valid_losses.append(loss.item())\n\n    t1 = format_time(time.time() - t0)\n    trn_loss = np.mean(train_losses)\n    val_loss = np.mean(valid_losses)\n    free, total = torch.cuda.mem_get_info(device=0)\n    mem_used = (total - free) / 1024**3\n    print(\n        f\"\\nEpoch: {epoch:02d}  Eğitim Kaybı: {trn_loss:.2f}  Doğrulama Kaybı: {val_loss:.2f}  GPU Kullanımı: {mem_used:.2f}GB  Geçen Süre: {t1}\"\n    )\n\n    if val_loss < best_val_loss:\n        best_val_loss = val_loss\n        epochs_wo_improvement = 0\n        torch.save(model.state_dict(), \"best_model.pth\")\n        print(f\"\\nYeni en iyi doğrulama kaybı: {val_loss:.2f}\\n\")\n    else:\n        epochs_wo_improvement += 1\n        print(f\"\\nİyileşme olmayan epoch sayısı: {epochs_wo_improvement}\\n\")\n\n    if epochs_wo_improvement == config[\"es_epochs\"]:\n        break\n\n    scheduler.step(val_loss)","metadata":{"_uuid":"bf788584-c943-460a-969c-5e3d985df731","_cell_guid":"dbdc3bbc-8c6c-47f4-bc6e-73eb7feee1f5","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-04-25T23:15:35.556150Z","iopub.execute_input":"2025-04-25T23:15:35.556399Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 4. Tahmin ve Gönderim\n\nTest verileri için tahminler yapılır ve yarışma formatına uygun bir `submission.csv` dosyası oluşturulur.","metadata":{"_uuid":"6f244978-2bfa-4749-83b6-731c8a9a97df","_cell_guid":"be21cba5-f88e-4126-b7fc-021a7b868582","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false}}},{"cell_type":"code","source":"# Tahmin ve gönderim\nt0 = time.time()\n\ntest_files = list(Path(os.path.join(config[\"data_path\"], \"test\")).glob(\"*.npy\"))\nx_cols = [f\"x_{i}\" for i in range(1, 70, 2)]\nfieldnames = [\"oid_ypos\"] + x_cols\nds = TestDataset(test_files)\ndl = DataLoader(ds, batch_size=4 * config[\"batch_size\"], num_workers=4, pin_memory=False)\n\nmodel.load_state_dict(torch.load(\"best_model.pth\", weights_only=True))\nmodel.eval()\n\nwith open(\"submission.csv\", \"wt\", newline=\"\") as csvfile:\n    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)\n    writer.writeheader()\n    for inputs, oids_test in dl:\n        inputs = inputs.to(device)\n        with torch.inference_mode():\n            with torch.autocast(device_type=\"cuda\"):\n                outputs = model(inputs)\n        y_preds = outputs[:, 0].cpu().numpy()\n        for y_pred, oid_test in zip(y_preds, oids_test):\n            for y_pos in range(70):\n                row = dict(zip(x_cols, [y_pred[y_pos, x_pos] for x_pos in range(1, 70, 2)]))\n                row[\"oid_ypos\"] = f\"{oid_test}_y_{y_pos}\"\n                writer.writerow(row)\n\nt1 = format_time(time.time() - t0)\nprint(f\"Tahmin Süresi: {t1}\")","metadata":{"_uuid":"d9cf5a07-196d-4a27-a620-161b868a4631","_cell_guid":"dcea17e9-ccc2-4d57-9f0b-8b51f7c4c6b7","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 5. Sonuçlar ve İyileştirme Önerileri\n\nBu çözüm, fizik tabanlı makine öğrenimi ile FWI problemini çözmek için güçlü bir UNet modeli sunar. Artık bağlantılar, modelin genelleştirme yeteneğini artırırken, OpenFWI veri setinin etkin kullanımı yüksek doğruluk sağlar.\n\n### İyileştirme Önerileri\n1. **Veri Artırımı**: Sismik verilere gürültü ekleme veya dönüşüm işlemleri uygulanabilir.\n2. **Hiperparametre Optimizasyonu**: `batch_size`, `lr`, `depth` gibi parametreler için grid search yapılabilir.\n3. **Ensemble Yöntemleri**: Farklı UNet modellerinin tahminleri birleştirilebilir.\n4. **Görselleştirme**: Eğitim ve doğrulama kayıplarını grafiklerle analiz edin.","metadata":{"_uuid":"49228de8-fc77-4295-a692-3ba0777eecf5","_cell_guid":"fd5badd6-7449-4267-83c9-ebe11ea8b5ec","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false}}},{"cell_type":"code","source":"# Örnek görselleştirme fonksiyonu\nimport matplotlib.pyplot as plt\n\ndef plot_sample(input_data, target, prediction):\n    \"\"\"\n    Sismik veri, gerçek ve tahmin edilen hız haritalarını görselleştirir.\n    \"\"\"\n    plt.figure(figsize=(15, 5))\n    plt.subplot(1, 3, 1)\n    plt.title(\"Sismik Veri\")\n    plt.imshow(input_data[0, 0, :, :], cmap=\"seismic\")\n    plt.subplot(1, 3, 2)\n    plt.title(\"Gerçek Hız Haritası\")\n    plt.imshow(target, cmap=\"viridis\")\n    plt.subplot(1, 3, 3)\n    plt.title(\"Tahmin Edilen Hız Haritası\")\n    plt.imshow(prediction, cmap=\"viridis\")\n    plt.show()","metadata":{"_uuid":"949ed068-2115-44fa-bad1-2bc8a5088046","_cell_guid":"4b41e2ea-52bc-4659-8654-085f22ce0b41","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 6. Kaggle Türkiye Topluluğuna Katkı\n\nBu not defteri, Kaggle topluluğuna aşağıdaki şekillerde katkıda bulunmayı amaçlar:\n- **Eğitici İçerik**: Kodun her bölümü ayrıntılı bir şekilde açıklanmıştır.\n- **Tekrarlanabilirlik**: `seed_everything` ile sonuçlar sabitlenir.\n- **Modülerlik**: Kod, düzenlenebilir ve genişletilebilir şekilde yapılandırılmıştır.\n- **Forum Katılımı**: Sorulara yanıt vermek ve diğer çözümleri tartışmak için Kaggle forumlarında aktif olun.\n\n**Kaggle Not Defteri Bağlantısı**: [🏆| GWI: UNet ile Fizik Tabanli FWI Cozumu |Turkce](https://www.kaggle.com/code/kayrahanozcan/gwi-unet-ile-fizik-tabanli-fwi-cozumu-turkce/)\n\nSorularınız veya önerileriniz için lütfen yorum bırakın! 🚀\n\n### Çalıştırma Talimatları\n1. Kaggle ortamında bir not defteri oluşturun.\n2. Bu içeriği kopyalayıp yapıştırın.\n3. Veri setini `/kaggle/input/waveform-inversion` yoluna bağlayın.\n4. GPU hızlandırıcısını etkinleştirin.\n5. Kod hücrelerini sırayla çalıştırın; model eğitilecek ve `submission.csv` oluşturulacaktır.","metadata":{"_uuid":"76ad9c1d-c030-48ba-818c-08599bbfe952","_cell_guid":"0a8a29df-1873-4cd6-adaa-2b4dafbc0def","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false}}}]}