<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tuğberk Akbulut</title>
    <description>The latest articles on DEV Community by Tuğberk Akbulut (@tuguberk).</description>
    <link>https://dev.to/tuguberk</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F800270%2F3de98f43-4325-419b-b148-bc224e2dd033.jpeg</url>
      <title>DEV Community: Tuğberk Akbulut</title>
      <link>https://dev.to/tuguberk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tuguberk"/>
    <language>en</language>
    <item>
      <title>What macOS dark wakes are and how to check if they're draining your battery</title>
      <dc:creator>Tuğberk Akbulut</dc:creator>
      <pubDate>Fri, 24 Jul 2026 09:01:47 +0000</pubDate>
      <link>https://dev.to/tuguberk/what-macos-dark-wakes-are-and-how-to-check-if-theyre-draining-your-battery-4m4b</link>
      <guid>https://dev.to/tuguberk/what-macos-dark-wakes-are-and-how-to-check-if-theyre-draining-your-battery-4m4b</guid>
      <description>&lt;p&gt;If your MacBook loses noticeable battery overnight even though it's closed and supposedly asleep, there's a good chance the cause is something Apple calls a dark wake.&lt;/p&gt;

&lt;p&gt;Normally when you close the lid, macOS puts the machine into full sleep CPU, display, most subsystems all powered down, drawing almost nothing. A dark wake is different: the machine briefly wakes itself up without turning the screen on or alerting you in any way, does some background work, and goes back to sleep. You never see it happen. It just shows up as battery loss you can't explain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why does this happen?
&lt;/h2&gt;

&lt;p&gt;The main driver is a feature called Power Nap, available on modern MacBooks. While the lid is closed and the Mac is on certain power states, Power Nap periodically wakes the machine to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;check and sync Mail, iCloud, and Calendar&lt;/li&gt;
&lt;li&gt;run Time Machine backups if one is due&lt;/li&gt;
&lt;li&gt;perform FileVault encryption background checks&lt;/li&gt;
&lt;li&gt;fetch software updates in the background&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these wake events is short, often just a couple of seconds, but they can happen very frequently. On a machine sitting idle for several days, that can mean well over a thousand dark wakes with barely a handful of actual user wake-ups (you opening the lid) in between. Individually tiny, cumulatively significant.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to check this on your own Mac
&lt;/h2&gt;

&lt;p&gt;You don't need any third-party tool to see the raw numbers, macOS tracks this itself. Open Terminal and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pmset &lt;span class="nt"&gt;-g&lt;/span&gt; stats
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prints lifetime counts since your last boot, including something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Sleeps: 812
DarkWakes: 1342
UserWakes: 6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your DarkWakes count is dramatically higher than your UserWakes count, Power Nap-driven activity is very likely what's been draining your battery.&lt;/p&gt;

&lt;p&gt;For a more detailed, timestamped breakdown of individual sleep/wake events (including the reason macOS logged for each one), you can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pmset &lt;span class="nt"&gt;-g&lt;/span&gt; log | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"Sleep|Wake|DarkWake"&lt;/span&gt; | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-50&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This shows the last 50 relevant log lines, so you can see the actual cadence, often every 10 to 15 minutes while idle.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you can do about it
&lt;/h2&gt;

&lt;p&gt;If this is costing you meaningful battery, you can turn Power Nap off:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;pmset &lt;span class="nt"&gt;-a&lt;/span&gt; powernap 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This disables it across all power sources. You'll lose the background mail/calendar sync and background Time Machine backups while the lid is closed, but for most people who plug in occasionally anyway, that trade-off is worth the battery life back.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping an eye on it going forward
&lt;/h2&gt;

&lt;p&gt;Checking this once with &lt;code&gt;pmset -g stats&lt;/code&gt; tells you what happened historically, but it doesn't show you what's happening right now, and going back to the terminal every time you're suspicious gets old fast. That's actually the exact problem that pushed me to build napwatch, a small Rust-based terminal app that shows a live, color-coded feed of Sleep/DarkWake/Wake events as they happen, alongside real-time per-process power draw and one-key toggles for Power Nap and other power settings, all in one screen. If you turn Power Nap off inside napwatch, you can literally watch the DarkWake entries stop appearing in real time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjv7550qw0yu6jrhrlscd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjv7550qw0yu6jrhrlscd.png" alt="Napwatch" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's open source and installable via Homebrew:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;Tuguberk/napwatch/napwatch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub: &lt;a href="https://github.com/Tuguberk/napwatch" rel="noopener noreferrer"&gt;https://github.com/Tuguberk/napwatch&lt;/a&gt;&lt;/p&gt;

</description>
      <category>macos</category>
      <category>productivity</category>
      <category>terminal</category>
      <category>sleep</category>
    </item>
    <item>
      <title>I built a terminal app to catch macOS dark wakes draining my MacBook's battery</title>
      <dc:creator>Tuğberk Akbulut</dc:creator>
      <pubDate>Fri, 24 Jul 2026 08:25:56 +0000</pubDate>
      <link>https://dev.to/tuguberk/i-built-a-terminal-app-to-catch-macos-dark-wakes-draining-my-macbooks-battery-323g</link>
      <guid>https://dev.to/tuguberk/i-built-a-terminal-app-to-catch-macos-dark-wakes-draining-my-macbooks-battery-323g</guid>
      <description>&lt;p&gt;A few days ago I opened my MacBook after it had been sitting closed for a while, and the battery was at 0%. Not a huge deal on its own, but it bothered me, the thing was closed, not doing anything, so where did the charge go?&lt;/p&gt;

&lt;p&gt;I didn't really know where to start, so I asked an AI to help me dig into it. What we found was pretty eye-opening: over about a week, my Mac had &lt;strong&gt;6 real user wake-ups vs. 1,342 dark wakes&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's actually happening
&lt;/h2&gt;

&lt;p&gt;Turns out this is caused by Power Nap. While the machine looks fully asleep, macOS quietly wakes it up roughly every 15 minutes to sync mail, iCloud, and Calendar, and to run FileVault health checks. Each wake only lasts a couple of seconds, but multiply that by hundreds of times over several idle days and it adds up to a real chunk of battery. The laptop was never actually fully asleep, it was just pretending to be, most of the time.&lt;/p&gt;

&lt;p&gt;I could've just flipped the Power Nap setting off in System Settings and moved on. But I wanted to actually &lt;em&gt;see&lt;/em&gt; this happening instead of taking it on faith once and forgetting about it, and I wanted a way to keep an eye on it going forward, not just fix it once.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building napwatch
&lt;/h2&gt;

&lt;p&gt;So I built &lt;strong&gt;napwatch&lt;/strong&gt;, a terminal app that watches for this continuously. It's written in Rust, using &lt;a href="https://github.com/ratatui/ratatui" rel="noopener noreferrer"&gt;ratatui&lt;/a&gt; for the UI and &lt;a href="https://github.com/crossterm-rs/crossterm" rel="noopener noreferrer"&gt;crossterm&lt;/a&gt; for terminal handling.&lt;/p&gt;

&lt;p&gt;The whole thing runs as one screen with three things visible at once:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What's eating power right now&lt;/strong&gt;: processes ranked by actual Watts, accurate from the very first reading instead of waiting a few minutes for an average to settle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Whether the machine is actually asleep&lt;/strong&gt;: a live, color-coded feed of Sleep / DarkWake / Wake events as they happen. Turning Power Nap off and watching the DarkWake entries stop appearing in real time was oddly satisfying the first time I tried it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Which power settings are currently on&lt;/strong&gt;: Power Nap, Low Power Mode, Standby, Wake-on-LAN, TCP Keepalive: and you can toggle any of them right from the app instead of digging through System Settings.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's also a detail view for any process (full path, parent process, launchd label, app bundle info if it's a bundled app), and you can terminate or renice a process without leaving the terminal.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it gets its data
&lt;/h2&gt;

&lt;p&gt;Nothing here talks to a private API. It's all standard macOS command-line tools, shelled out to and parsed:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;th&gt;Used for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pmset -g batt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Battery percentage, charging state, time remaining&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pmset -g stats&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lifetime sleep/dark-wake/user-wake counts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pmset -g log&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sleep/wake event history for the live feed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ioreg -rn AppleSmartBattery&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Instant amperage/voltage/capacity for the real-time Watts figure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;top -l 2 -o power&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Per-process energy-impact ranking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;ps&lt;/code&gt; / &lt;code&gt;launchctl list&lt;/code&gt; / &lt;code&gt;plutil -extract&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Process detail and app bundle info&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A couple of things worth calling out from actually building this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Instant power draw is trickier than it sounds.&lt;/strong&gt; An earlier version tried to derive a drain rate from whole-percentage battery deltas over a rolling window, which meant waiting a few minutes before the number meant anything. Computing it from &lt;code&gt;ioreg&lt;/code&gt;'s instant amperage/voltage/capacity fields instead gives a correct number from the first poll.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;top -l 1&lt;/code&gt; always reads 0 for every process.&lt;/strong&gt; Power is a rate, so it needs a delta between two samples. napwatch runs &lt;code&gt;top -l 2&lt;/code&gt; and only keeps the second sample.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;pmset -g log&lt;/code&gt; has no since/tail flag&lt;/strong&gt; — it always dumps the entire history, which gets slow once the log has days of entries in it. So it's polled on its own slower cadence rather than every tick, and the live feed seeds with just the last few historical events on startup instead of replaying everything.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Trying it out
&lt;/h2&gt;

&lt;p&gt;It's macOS only, and installable via Homebrew:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;Tuguberk/napwatch/napwatch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or build from source if you have Rust installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Tuguberk/napwatch.git
&lt;span class="nb"&gt;cd &lt;/span&gt;napwatch
cargo &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--path&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's fully open source under MIT: &lt;a href="https://github.com/Tuguberk/napwatch" rel="noopener noreferrer"&gt;github.com/Tuguberk/napwatch&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If your Mac's battery has ever done something similarly weird while "asleep," I'd be curious whether you're seeing the same dark-wake pattern. And if you find it useful, a star on the repo is always appreciated.&lt;/p&gt;

</description>
      <category>macbook</category>
      <category>rust</category>
      <category>tui</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Dünya Kupası 2026 Maç Sonuçlarını AI ile Nasıl Tahmin Ettim?</title>
      <dc:creator>Tuğberk Akbulut</dc:creator>
      <pubDate>Mon, 15 Jun 2026 12:21:42 +0000</pubDate>
      <link>https://dev.to/tuguberk/dunya-kupasi-2026-mac-sonuclarini-ai-ile-nasil-tahmin-ettim-287p</link>
      <guid>https://dev.to/tuguberk/dunya-kupasi-2026-mac-sonuclarini-ai-ile-nasil-tahmin-ettim-287p</guid>
      <description>&lt;h2&gt;
  
  
  WC 2026 Maç Sonuçlarını AI ile Nasıl Tahmin Ettim?
&lt;/h2&gt;

&lt;p&gt;Geçen dönem Probability &amp;amp; Statistics dersini alırken aklımda sürekli şu soru vardı: &lt;em&gt;"Bunları gerçek hayatta nasıl kullanacağım?"&lt;/em&gt; Formüller anlamlıydı, sınavlar güzeldi ama uygulaması nerede?&lt;/p&gt;

&lt;p&gt;Cevap beklenmedik bir yerden geldi: Dünya Kupası 2026.&lt;/p&gt;

&lt;p&gt;Bu yazıda sıfırdan kurduğum bir futbol tahmin sistemini anlatacağım. Sadece "şu kütüphaneyi kullan" değil, &lt;strong&gt;neden bu modeli seçtim, rakipleriyle nasıl karşılaştırdım, matematiği nasıl çalışıyor&lt;/strong&gt; bunların hepsini adım adım açıklayacağım.&lt;/p&gt;

&lt;p&gt;Spoiler: Model şu an %55 doğrulukla çalışıyor. Bu iyi mi? Kötü mü? Yazının sonunda anlayacaksınız.&lt;/p&gt;




&lt;h2&gt;
  
  
  Önce Problem: Futbol Neden Bu Kadar Zor?
&lt;/h2&gt;

&lt;p&gt;Futbol tahmin etmek kulağa kolay gelir. Ama şunu düşünün:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bir maçta ortalama &lt;strong&gt;2.5 gol&lt;/strong&gt; atılır. Poisson dağılımı için bu düşük bir lambda demek, yani rastgelelik çok yüksek.&lt;/li&gt;
&lt;li&gt;Favoriler her zaman kazanmıyor. Tarihsel veriye bakarsanız &lt;strong&gt;ev sahibi takımlar ancak %45 oranında&lt;/strong&gt; kazanıyor.&lt;/li&gt;
&lt;li&gt;90 dakikada tek bir hata maçı değiştirebilir.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Akademisyenler bunu "düşük sinyalli yüksek gürültülü ortam" olarak tanımlar. Hava durumu tahmini ya da hisse senedi tahmininden bile zordur, çünkü insan faktörü (motivasyon, formun o günkü hali, taktik tercih) ölçülmesi neredeyse imkânsız değişkenler içerir.&lt;/p&gt;

&lt;p&gt;Bu yüzden modeli kurmadan önce kendime şunu sordum: &lt;strong&gt;Ne kadar iyi olmak mümkün?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cevap: Dünyanın en iyi sistemleri &lt;strong&gt;%55-58&lt;/strong&gt; doğruluk elde ediyor. Bu bizim hedefimizdi.&lt;/p&gt;




&lt;h2&gt;
  
  
  Neden LLM Kullanmadım?
&lt;/h2&gt;

&lt;p&gt;İlk düşünce herkesin düşündüğü şey: &lt;em&gt;"ChatGPT'ye sorarım, o tahmin eder."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Denedim. Claude'a "Türkiye - ABD maçında kim kazanır, olasılık ver" dedim. Cevap geldi: "%40 Türkiye favori."&lt;/p&gt;

&lt;p&gt;Ama bu sayı &lt;strong&gt;kalibre değil.&lt;/strong&gt; Yani Claude'un söylediği %40, gerçek hayatta %40 gerçekleşme olasılığını temsil etmiyor. Aynı soruyu 10 kez sor, 10 farklı sayı alırsın. LLM'ler tutarlı, kalibre olasılık üretemez.&lt;/p&gt;

&lt;p&gt;Daha da önemlisi: &lt;strong&gt;geçmiş veriden öğrenmiyor.&lt;/strong&gt; 49.000 tarihsel maçı "biliyor" ama bu bilgi içselleştirilmiş, matematiksel bir model değil. Hallucination riski yüksek.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LLM: "Türkiye güçlü bir takım, %40 şansları var"
İstatistiksel model: "49.000 maç, Elo farkı, son form, FIFA sıralaması → %33"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;İkincisi &lt;strong&gt;açıklanabilir, tekrarlanabilir ve kalibre edilebilir.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;LLM'nin gerçekten işe yarayabileceği tek alan: yapısal olmayan bilgi sakatlık haberleri, basın toplantıları, taktik analizler. Bunları gelecekte bir "agent" olarak sisteme eklemek istedim. Ama temel model istatistik olmalıydı.&lt;/p&gt;




&lt;h2&gt;
  
  
  Mimari: Üç Katman
&lt;/h2&gt;

&lt;p&gt;Sistemin genel yapısını görelim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────┐
│  VERİ KATMANI                                               │
│  49k+ tarihsel maç · FIFA sıralaması · WC2026 fikstür       │
└─────────────────────────┬───────────────────────────────────┘
                          │
          ┌───────────────┼───────────────┐
          ▼               ▼               ▼
   ┌─────────────┐ ┌─────────────┐ ┌──────────────┐
   │  Bayesian   │ │  LightGBM   │ │   Piyasa     │
   │  Poisson    │ │  23 özellik │ │   Verileri   │
   └──────┬──────┘ └──────┬──────┘ └──────┬───────┘
          └───────────────┼───────────────┘
                          ▼
               ┌──────────────────┐
               │ Ağırlıklı Birleş │
               │ + Kalibrasyon    │
               └────────┬─────────┘
                        ▼
            ┌───────────────────────┐
            │  25.000 × MC Sim      │
            │  Bracket Olasılıkları │
            └───────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Her katmanı sırayla anlatalım.&lt;/p&gt;




&lt;h2&gt;
  
  
  Katman 1: Hierarchical Bayesian Poisson Modeli
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Neden Poisson?
&lt;/h3&gt;

&lt;p&gt;Gol sayısı ayrık (0, 1, 2, 3...) ve nadiren büyük değerler alıyor. Bu tam Poisson dağılımının tanımı:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;         λᵏ · e⁻λ
P(X=k) = ─────────     (k = 0, 1, 2, ...)
            k!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ama hangi lambda? İşte burada Bayesian modeli devreye giriyor.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hiyerarşik Yapı
&lt;/h3&gt;

&lt;p&gt;Her takımın gizli (latent) &lt;strong&gt;atak&lt;/strong&gt; ve &lt;strong&gt;savunma&lt;/strong&gt; gücü var:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Matematiksel gösterim (PyMC ile implement edildi)
&lt;/span&gt;
&lt;span class="n"&gt;attack&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="o"&gt;~&lt;/span&gt; &lt;span class="nc"&gt;Normal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;μ_att&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;σ_att&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# tüm takımlar aynı prior'ı paylaşır
&lt;/span&gt;&lt;span class="n"&gt;defense&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt; &lt;span class="nc"&gt;Normal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;μ_def&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;σ_def&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;λ_home&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;intercept&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;home_adv&lt;/span&gt; &lt;span class="err"&gt;×&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;neutral&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;attack&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;home&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;defense&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;away&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;λ_away&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;intercept&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;attack&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;away&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;defense&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;home&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;home_goals&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt; &lt;span class="nc"&gt;Poisson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;λ_home&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;away_goals&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt; &lt;span class="nc"&gt;Poisson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;λ_away&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Neden hiyerarşik?&lt;/strong&gt; Küçük takımlar hakkında az veri var. Hiyerarşik yapı, az veri olan takımların tahminlerini genel ortalamayla "düzleştirir" (shrinkage). Bu klasik istatistikte &lt;strong&gt;Stein paradoksu&lt;/strong&gt;nun pratik uygulaması.&lt;/p&gt;

&lt;h3&gt;
  
  
  Zaman Ağırlıkları
&lt;/h3&gt;

&lt;p&gt;2010'daki Türkiye ile 2025'teki Türkiye aynı takım değil. 8 yıl önceki maçların bu anki tahmine etkisi ne olmalı?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Yarı-ömür weighting:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# t gün önceki maçın ağırlığı
&lt;/span&gt;&lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;days_ago&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;730&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# 730 gün (2 yıl) önce → ağırlık = 0.5
# 4 yıl önce → ağırlık = 0.25
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bu exponential decay, fizikteki radyoaktif bozunma formülüyle aynı. Derste öğrendiğimiz bir şeyi burada görebiliyorum,güzel bir detay.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌──────────────────────────────────────────────────────────────┐
│                      Bayes Teoremi                           │
│                                                              │
│      P(θ | X)   =   P(X | θ)  ×  P(θ)  /  P(X)               │
│                                                              │
│  P(θ | X)  ← Posterior   "Veriyi gördükten sonra inanç"      │
│  P(X | θ)  ← Likelihood  "Veri modelle ne kadar uyuyor?"     │
│  P(θ)      ← Prior       "Veri öncesi ön bilgi"              │
│  P(X)      ← Evidence    "Normalleştirme sabiti"             │
└──────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Neden Bayesian, Frekantist Değil?
&lt;/h3&gt;

&lt;p&gt;Klasik (frekantist) yaklaşım: maksimum likelihood ile parametre tahmin et, tek bir değer al.&lt;/p&gt;

&lt;p&gt;Bayesian yaklaşım: &lt;strong&gt;posterior dağılımı&lt;/strong&gt; hesapla, yani parametrenin olası değerlerinin tüm dağılımını elde et.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;P(parametreler | veri) ∝ P(veri | parametreler) × P(parametreler)
     posterior              likelihood               prior
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bunun pratikte anlamı: &lt;strong&gt;belirsizliği sayısallaştırabiliyorsun.&lt;/strong&gt; "Türkiye'nin atak gücü 0.3" demek yerine "Türkiye'nin atak gücü %95 olasılıkla [0.1, 0.5] arasında" diyebiliyorsun.&lt;/p&gt;

&lt;p&gt;PyMC ile implement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pymc&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pm&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;football_model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Hyperpriors
&lt;/span&gt;    &lt;span class="n"&gt;mu_att&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Normal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mu_att&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sigma&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sigma_att&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;HalfNormal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sigma_att&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sigma&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Team-level attack and defense
&lt;/span&gt;    &lt;span class="n"&gt;attack&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Normal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;attack&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mu_att&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="n"&gt;sigma&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sigma_att&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;n_teams&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;defense&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Normal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;defense&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sigma&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;n_teams&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Home advantage
&lt;/span&gt;    &lt;span class="n"&gt;home_adv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Normal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;home_adv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sigma&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;intercept&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Normal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;intercept&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sigma&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Expected goals
&lt;/span&gt;    &lt;span class="n"&gt;log_lambda_home&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;intercept&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;home_adv&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;neutral&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;attack&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;home_idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;defense&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;away_idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;log_lambda_away&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;intercept&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;attack&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;away_idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;defense&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;home_idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# Likelihood (weighted)
&lt;/span&gt;    &lt;span class="n"&gt;home_goals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Poisson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;home_goals&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log_lambda_home&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                             &lt;span class="n"&gt;observed&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;home_goals_obs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;away_goals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Poisson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;away_goals&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log_lambda_away&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                             &lt;span class="n"&gt;observed&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;away_goals_obs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# MCMC sampling
&lt;/span&gt;    &lt;span class="n"&gt;trace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;draws&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tune&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chains&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_accept&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;MCMC (Markov Chain Monte Carlo) bu posterior'u örnekleyerek hesaplıyor. Her sampling ~90 saniye sürüyor. Deterministik bir çözüm yok, örnekleme var.&lt;/p&gt;




&lt;h2&gt;
  
  
  Katman 2: LightGBM ile Makine Öğrenmesi
&lt;/h2&gt;

&lt;p&gt;Bayesian model güçlü ama sınırlı: sadece gol verisi kullanıyor. &lt;strong&gt;Elo puanları, son form, FIFA sıralaması&lt;/strong&gt; gibi özellikler eklemek için ikinci bir model kurdum.&lt;/p&gt;

&lt;h3&gt;
  
  
  Özellik Mühendisliği: 23 Sinyal
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;FEATURE_COLS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;# Elo
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;elo_diff&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;home_elo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;away_elo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;# Son form (son 5 maç)
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;home_win_rate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;away_win_rate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;home_gd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;away_gd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c1"&gt;# averaj
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;home_gf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;away_gf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c1"&gt;# atılan gol
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;home_ga&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;away_ga&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c1"&gt;# yenilen gol
&lt;/span&gt;    &lt;span class="c1"&gt;# FIFA sıralaması
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;home_fifa_rank&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;away_fifa_rank&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fifa_rank_diff&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;home_fifa_pts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;away_fifa_pts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fifa_pts_diff&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;# Bağlam
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tournament_importance&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;is_neutral&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;home_rest&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;away_rest&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="c1"&gt;# dinlenme günü
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;home_draw_rate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;away_draw_rate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Elo Puanı Nedir?
&lt;/h3&gt;

&lt;p&gt;Satranç dünyasından gelen bir sıralama sistemi. Basit fikir: kazandığında rakibinden puan alırsın, kaybettiğinde verirsin. Kazanma ihtimalin ne kadar düşükse, kazandığında o kadar çok puan alırsın.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update_elo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rating_a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rating_b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;result: 1=A kazandı, 0.5=beraberlik, 0=B kazandı&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;expected_a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;rating_b&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;rating_a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;expected_a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;rating_a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rating_b&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;49.000 tarihsel maçı baştan sona geçirerek her takım için güncel Elo puanı hesapladım. Bu özellik, LightGBM'in en önemli girdilerinden biri oldu.&lt;/p&gt;

&lt;h3&gt;
  
  
  FIFA Sıralaması: Veri Sızıntısına Dikkat
&lt;/h3&gt;

&lt;p&gt;Burada kritik bir hata yaptım ve düzelttim.&lt;/p&gt;

&lt;p&gt;İlk versiyonda FIFA sıralaması olarak "bugünkü sıralamayı" kullanıyordum. Ama 2018 maçını tahmin ederken 2024 sıralaması kullanmak &lt;strong&gt;veri sızıntısı&lt;/strong&gt; (data leakage). Gelecek bilgisini geçmiş tahminlerine sokmuş oluyorsun.&lt;/p&gt;

&lt;p&gt;Çözüm: Her maç için o maçın oynandığı tarihteki sıralamayı çek.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fifa_rank_at&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lookup&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Maç tarihindeki FIFA sıralamasını döndür (leakage-free).&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;team&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;lookup&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mf"&gt;150.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;  &lt;span class="c1"&gt;# bilinmeyen takım → konservatif fallback
&lt;/span&gt;
    &lt;span class="n"&gt;ts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lookup&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# takımın tüm sıralama geçmişi
&lt;/span&gt;    &lt;span class="n"&gt;past&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;past&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mf"&gt;150.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;

    &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;past&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# maç tarihinden önceki en son sıralama
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rank&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;points&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bu detay küçük görünüyor ama model doğruluğu açısından kritik. Leakage'ı keşfetmek için ayrı bir test yazdım:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_no_future_leakage&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Hiçbir özellik maç tarihinden sonraki veriyi kullanmamalı.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;features&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;iterrows&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;match_date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;fifa_date&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fifa_rank_lookup_date&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;fifa_date&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;match_date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LEAKAGE: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;match_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3-Way Train/Val/Test Split
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tarih sırası:  [──── TRAIN ────][─ VAL ─][─ TEST ─]
                2017-2023        2023-24   2024-25
                  5754 maç        1062      981
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neden böyle? Finansal zaman serilerinde de aynı kural: &lt;strong&gt;geçmişle geleceği tahmin edersin, geleceğin bilgisiyle geçmişi eğitmezsin.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Random split kullanmak burada yanıltıcı olurdu, model geleceği öğrenmiş gibi görünürdü.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;lightgbm&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;LGBMClassifier&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LGBMClassifier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;n_estimators&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;learning_rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;num_leaves&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;objective&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;multiclass&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# H / D / A
&lt;/span&gt;    &lt;span class="n"&gt;num_class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;class_weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;balanced&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# maçların %46'sı ev sahibi galibiyeti dengesiz
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;X_train&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_train&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;eval_set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;X_val&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_val&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
    &lt;span class="n"&gt;callbacks&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;early_stopping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Katman 3: Kalibrasyon
&lt;/h2&gt;

&lt;p&gt;İki modeli birleştirdim, güzel olasılıklar ürettim. Ama bunlara güvenebilir miyim?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kalibrasyon testi:&lt;/strong&gt; Modelin %70 dediği maçlarda, takım gerçekten %70 kez kazanıyor mu?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F265emhfwtt9orfz740sa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F265emhfwtt9orfz740sa.png" alt="Isotonic Regression" width="800" height="603"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Çoğu model bu testte başarısız olur. Özellikle tree-based modeller sistematik olarak aşırı güvenir (over-confident).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Isotonic Regresyon ile Düzeltme:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sklearn.isotonic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;IsotonicRegression&lt;/span&gt;

&lt;span class="c1"&gt;# Her sınıf için ayrı kalibratör
&lt;/span&gt;&lt;span class="n"&gt;calibrators&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;H&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;p_home&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;D&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;p_draw&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;p_away&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)]:&lt;/span&gt;
    &lt;span class="n"&gt;cal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;IsotonicRegression&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out_of_bounds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;clip&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;y_bin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val_df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;actual_outcome&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;cal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val_df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;y_bin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;calibrators&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isotonic regresyon monoton (düz artan) bir dönüşüm uygular. Model %70 diyorsa ama gerçekte %65 oluyor, bunu %65'e çeker. Basit ama etkili.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Önce/Sonra Brier skoru:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kalibrasyonsuz: 0.561&lt;/li&gt;
&lt;li&gt;Kalibrasyonlu: 0.538&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Monte Carlo Turnuva Simülasyonu
&lt;/h2&gt;

&lt;p&gt;Artık her maç için kalibre olasılıklar var. 25.000 kez turnuvayı baştan sona simüle ettim.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;simulate_full_tournament&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;all_groups&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;played&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;25_000&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;reach&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;  &lt;span class="c1"&gt;# her takım için kaç kez hangi aşamaya geldi
&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# 1. Grup aşamasını simüle et
&lt;/span&gt;        &lt;span class="n"&gt;group_results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;grp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;teams&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;all_groups&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;group_results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;grp&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;simulate_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;teams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;played&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;grp&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# 2. İlk 2 + en iyi 8 üçüncüyü belirle
&lt;/span&gt;        &lt;span class="n"&gt;qualifiers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;determine_qualifiers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group_results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# 3. Eleme turlarını simüle et
&lt;/span&gt;        &lt;span class="n"&gt;bracket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;seed_bracket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qualifiers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;simulate_knockouts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bracket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reach&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Olasılık = kaç kez ulaştı / toplam simülasyon
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;counts&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;counts&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;reach&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Her simülasyon 32 takımın tüm yolculuğunu oynar. 25.000 × ~100 maç = 2.5 milyon sanal maç!&lt;/p&gt;

&lt;h3&gt;
  
  
  Wilson Güven Aralıkları
&lt;/h3&gt;

&lt;p&gt;25.000 simülasyondan Türkiye'nin final oynama olasılığı %0.2 çıktı. Bu tahmine ne kadar güvenelim?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wilson score interval&lt;/strong&gt; (Wilson, 1927):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wilson_ci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.96&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;k başarı, n deneme için %95 güven aralığı.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
    &lt;span class="n"&gt;denom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
    &lt;span class="n"&gt;centre&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;denom&lt;/span&gt;
    &lt;span class="n"&gt;half&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;denom&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;centre&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;half&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;centre&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;half&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Türkiye final: 50/25000
&lt;/span&gt;&lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wilson_ci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# → (%0.15, %0.26)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Normal approximation (ders kitabındaki yöntem) burada işe yaramaz çünkü oran çok küçük. Wilson interval küçük oranlar için çok daha güvenilir.&lt;/p&gt;




&lt;h2&gt;
  
  
  Sonuçlar: Dürüst Bir Değerlendirme
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Brier Skoru ↓&lt;/th&gt;
&lt;th&gt;Doğruluk ↑&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Birleşik Model&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.541&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;%55.2&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bayesian Poisson&lt;/td&gt;
&lt;td&gt;0.543&lt;/td&gt;
&lt;td&gt;%56.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LightGBM&lt;/td&gt;
&lt;td&gt;0.552&lt;/td&gt;
&lt;td&gt;%55.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kıyaslama: eşit şans&lt;/td&gt;
&lt;td&gt;0.667&lt;/td&gt;
&lt;td&gt;%33.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kıyaslama: hep ev sahibi&lt;/td&gt;
&lt;td&gt;0.648&lt;/td&gt;
&lt;td&gt;%44.6&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Brier skoru nedir?&lt;/strong&gt; Tahmin vektörü ile gerçek vektör arasındaki ortalama karesel hata. 0 mükemmel, 0.667 tamamen rastgele.&lt;/p&gt;

&lt;p&gt;Modelimiz rastgeleden %19 daha iyi. "Hep ev sahibi kazanır" de ki naif stratejiyi de geride bırakıyor.&lt;/p&gt;

&lt;p&gt;%55 doğruluk ilk bakışta düşük görünebilir. Ama şunu düşünün:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Dünyanın en büyük organizasyonları, milyarlarca veri noktası ve yüzlerce analist ile bu işe giren sistemler bile %57'nin üzerine nadiren çıkıyor.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Futbol bu. Rastgelelik bu sporun özünde var. Modelimizin değeri kesin kazananı bulmak değil, &lt;strong&gt;olasılıkları doğru kalibre etmek.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Türkiye'nin Görünümü
&lt;/h3&gt;

&lt;p&gt;WC2026 başladığında (15 Haziran 2026 itibarıyla) modelimizin hesapları:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aşama&lt;/th&gt;
&lt;th&gt;Olasılık&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Grup aşamasından çıkma&lt;/td&gt;
&lt;td&gt;%33&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Son 16&lt;/td&gt;
&lt;td&gt;%10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Çeyrek Final&lt;/td&gt;
&lt;td&gt;%2.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Yarı Final&lt;/td&gt;
&lt;td&gt;%0.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Şampiyon&lt;/td&gt;
&lt;td&gt;%0.05&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Türkiye Grup D'de (Paraguay, Avustralya, ABD ile) %1 ihtimalle birinci, %9 ihtimalle ikinci bitirebilir. Ama %46 ihtimalle üçüncü bitirecek ve bu grubun en iyi üçüncüsü olursa yine tutarlı. Toplam eleme şansı: &lt;strong&gt;%33&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Öğrendiklerim
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Kalibrasyon doğruluktan önemli.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Model doğruluğu sizi yanıltabilir. %55 doğru tahmin eden ama kalibre olmayan model, %52 doğru tahmin eden ama kalibre olan modelden daha az kullanışlıdır. Özellikle olasılıklarla karar alıyorsanız.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Veri sızıntısı (leakage) gizli kalmayı sever.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
FIFA sıralaması örneği gibi, leakage bazen çok açık değil. Test setinde fazla iyi sonuç görüyorsanız iki kez kontrol edin.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Baseline model kurmadan başlamayın.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
"Hep ev sahibi kazanır" modelim %44.6 doğrulukla çalışıyor. Bunu geçemeyen bir model geliştirmek zaman kaybı. Her zaman naive baseline'ı önce kurun.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Bayesian düşünmek farklı bir zihin açıyor.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Frekantist: "Parametre nedir?" → tek cevap&lt;br&gt;&lt;br&gt;
Bayesian: "Parametre ne olabilir?" → dağılım&lt;br&gt;&lt;br&gt;
Bu fark gerçek verilerle çalışırken devasa bir avantaj.&lt;/p&gt;




&lt;h2&gt;
  
  
  Kodu Görmek İster misiniz?
&lt;/h2&gt;

&lt;p&gt;Tüm kaynak kodu GitHub'da açık:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;&lt;a href="https://github.com/Tuguberk/wc2026-ai" rel="noopener noreferrer"&gt;github.com/Tuguberk/wc2026-ai&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Canlı demo:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;&lt;a href="https://wc2026-ai.streamlit.app" rel="noopener noreferrer"&gt;wc2026-ai.streamlit.app&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Sıradaki Adım: LLM Hibrit Mimarisi
&lt;/h2&gt;

&lt;p&gt;Bu sistem iyi çalışıyor ama kritik bir eksik var: &lt;strong&gt;sakatlık ve kadro bilgisi yok.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Maç öncesi "Çalhanoğlu yok" haberi modeli tamamen değiştirmeli. Bunu istatistiksel modelle yapamazsın, yapısal olmayan metinden bilgi çıkarman lazım.&lt;/p&gt;

&lt;p&gt;İstatistiksel backbone kalır (kalibre, tekrarlanabilir, açıklanabilir).&lt;br&gt;&lt;br&gt;
LLM agent yapısal olmayan dünyayı sayıya dönüştürür.&lt;br&gt;&lt;br&gt;
İki güçlü yaklaşım bir arada.&lt;/p&gt;




&lt;h2&gt;
  
  
  Kaynaklar
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dixon &amp;amp; Coles (1997)&lt;/strong&gt; — &lt;em&gt;Modelling Association Football Scores and Inefficiencies in the Football Betting Market&lt;/em&gt; — bu alanın klasiği, temel formülasyonu buradan aldım&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maher (1982)&lt;/strong&gt; — &lt;em&gt;Modelling Association Football Scores&lt;/em&gt; — Poisson bağımsızlık varsayımının kökeni&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Karlis &amp;amp; Ntzoufras (2003)&lt;/strong&gt; — &lt;em&gt;Analysis of sports data by using bivariate Poisson models&lt;/em&gt; — çift Poisson modeli&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wilson (1927)&lt;/strong&gt; — &lt;em&gt;Probable inference, the law of succession, and statistical inference&lt;/em&gt; — Wilson CI'nın orijinal makalesi&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gelman et al.&lt;/strong&gt; — &lt;em&gt;Bayesian Data Analysis&lt;/em&gt; — Bayesian düşüncenin İncil'i&lt;/li&gt;
&lt;li&gt;PyMC documentation — &lt;a href="https://docs.pymc.io" rel="noopener noreferrer"&gt;docs.pymc.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;LightGBM paper — Ke et al., NeurIPS 2017&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;*Bu projeyi WC2026 boyunca aktif olarak güncellemeye çalışacağım. Her maçtan sonra &lt;code&gt;make update&lt;/code&gt; → &lt;code&gt;git push&lt;/code&gt; → Streamlit otomatik güncelleniyor.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sorularınız veya önerileriniz için yorumları kullanabilirsiniz.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>statistics</category>
      <category>football</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
