<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://sonsuzus.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://sonsuzus.github.io/" rel="alternate" type="text/html" /><updated>2026-08-07T07:13:28+00:00</updated><id>https://sonsuzus.github.io/feed.xml</id><title type="html">SonsuzUs</title><subtitle>Programlama ve Yazılım</subtitle><author><name>Sonsuz Us</name></author><entry><title type="html">Biyometrik Örüntü Tanıma: Parmak İzi ve İris Eşleştirme Sistemi</title><link href="https://sonsuzus.github.io/posts/biyometrik-oruntu-tanima-parmak-izi-ve-iris-eslestirme-sistemi/" rel="alternate" type="text/html" title="Biyometrik Örüntü Tanıma: Parmak İzi ve İris Eşleştirme Sistemi" /><published>2026-08-07T00:00:00+00:00</published><updated>2026-08-07T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/biyometrik-oruntu-tanima-parmak-izi-ve-iris-eslestirme-sistemi</id><content type="html" xml:base="https://sonsuzus.github.io/posts/biyometrik-oruntu-tanima-parmak-izi-ve-iris-eslestirme-sistemi/"><![CDATA[<p>Telefonun kilidini parmağınla açarken cihazın içinde minik bir dedektif çalışır: Görüntüyü temizler, ayırt edici özellikleri çıkarır ve bunları kayıtlı şablonla karşılaştırır. Bu projede gerçek kişisel veriler toplamadan, parmak izi veya iris verisini temsil eden yapay özellik vektörleriyle temel bir biyometrik eşleştirme sisteminin mantığını inceleyeceğiz.</p>

<p>``</p>

<h2 id="biyometrik-eşleştirme-nasıl-çalışır">Biyometrik eşleştirme nasıl çalışır?</h2>

<p>Bir biyometrik sistem ham görüntüleri doğrudan karşılaştırmak yerine genellikle <strong>şablon</strong> adı verilen sayısal temsiller üretir. Parmak izinde çizgi sonları ve çatallanmalar; iriste ise doku frekansları, halkalar ve yerel desenler özellik olarak kullanılabilir.</p>

<p>Tipik işlem hattı şöyledir:</p>

<ol>
  <li>Sensörden görüntü alınır.</li>
  <li>Gürültü azaltılır ve görüntü normalize edilir.</li>
  <li>İlgi bölgesi belirlenir.</li>
  <li>Ayırt edici özellikler çıkarılır.</li>
  <li>Özellik vektörü kayıtlı şablonla karşılaştırılır.</li>
  <li>Benzerlik belirlenen eşiği geçiyorsa eşleşme kabul edilir.</li>
</ol>

<table>
  <thead>
    <tr>
      <th>Aşama</th>
      <th>Parmak izi örneği</th>
      <th>İris örneği</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Ön işleme</td>
      <td>Çizgileri belirginleştirme</td>
      <td>Göz bebeğini ayırma</td>
    </tr>
    <tr>
      <td>Özellik</td>
      <td>Minutiae noktaları</td>
      <td>Doku kodları</td>
    </tr>
    <tr>
      <td>Sorun</td>
      <td>Parmağın kayması</td>
      <td>Göz kapağı ve yansıma</td>
    </tr>
    <tr>
      <td>Temsil</td>
      <td>Nokta ve yön listesi</td>
      <td>İkili veya sayısal vektör</td>
    </tr>
  </tbody>
</table>

<h2 id="benzerliği-matematikle-ölçmek">Benzerliği matematikle ölçmek</h2>

<p>İki özellik vektörü arasındaki uzaklık için Öklid uzaklığı kullanılabilir. Kayıtlı şablon $x$, yeni örnek $y$ ise:</p>

\[d(x,y)=\sqrt{\sum_{i=1}^{n}(x_i-y_i)^2}\]

<p>Uzaklık küçüldükçe örnekler birbirine daha çok benzer. Benzerlik puanını $[0,1]$ aralığına taşımak için basitçe şu dönüşüm uygulanabilir:</p>

\[s(x,y)=\frac{1}{1+d(x,y)}\]

<p>Karar kuralımız $s \geq t$ olabilir. Buradaki $t$ eşik değeridir. Eşiği yükseltmek güvenliği artırabilir ancak gerçek kullanıcıların reddedilmesine de yol açabilir.</p>

<table>
  <thead>
    <tr>
      <th>Eşik tercihi</th>
      <th>Avantaj</th>
      <th>Dezavantaj</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Düşük</td>
      <td>Kullanım daha rahat</td>
      <td>Yanlış kabul artabilir</td>
    </tr>
    <tr>
      <td>Yüksek</td>
      <td>Yetkisiz kabul azalabilir</td>
      <td>Yanlış ret artabilir</td>
    </tr>
    <tr>
      <td>Dengeli</td>
      <td>İki hata türünü dengeler</td>
      <td>Test verisi gerektirir</td>
    </tr>
  </tbody>
</table>

<h2 id="python-ile-basit-prototip">Python ile basit prototip</h2>

<p>Aşağıdaki kod gerçek görüntüler yerine sentetik biyometrik vektörler kullanır. Böylece kişisel veri toplamadan eşleştirme mekanizmasını deneyebiliriz.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">numpy</span> <span class="k">as</span> <span class="n">np</span>

<span class="k">class</span> <span class="nc">BiometricMatcher</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">threshold</span><span class="o">=</span><span class="mf">0.80</span><span class="p">):</span>
        <span class="n">self</span><span class="p">.</span><span class="n">threshold</span> <span class="o">=</span> <span class="n">threshold</span>
        <span class="n">self</span><span class="p">.</span><span class="n">templates</span> <span class="o">=</span> <span class="p">{}</span>

    <span class="k">def</span> <span class="nf">enroll</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">user_id</span><span class="p">,</span> <span class="n">features</span><span class="p">):</span>
        <span class="n">vector</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">asarray</span><span class="p">(</span><span class="n">features</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="nb">float</span><span class="p">)</span>
        <span class="n">norm</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">linalg</span><span class="p">.</span><span class="nf">norm</span><span class="p">(</span><span class="n">vector</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">norm</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">raise</span> <span class="nc">ValueError</span><span class="p">(</span><span class="sh">"</span><span class="s">Sıfır vektörü kaydedilemez.</span><span class="sh">"</span><span class="p">)</span>
        <span class="n">self</span><span class="p">.</span><span class="n">templates</span><span class="p">[</span><span class="n">user_id</span><span class="p">]</span> <span class="o">=</span> <span class="n">vector</span> <span class="o">/</span> <span class="n">norm</span>

    <span class="k">def</span> <span class="nf">verify</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">user_id</span><span class="p">,</span> <span class="n">sample</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">user_id</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">self</span><span class="p">.</span><span class="n">templates</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">False</span><span class="p">,</span> <span class="mf">0.0</span>

        <span class="n">sample</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">asarray</span><span class="p">(</span><span class="n">sample</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="nb">float</span><span class="p">)</span>
        <span class="n">norm</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">linalg</span><span class="p">.</span><span class="nf">norm</span><span class="p">(</span><span class="n">sample</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">norm</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">False</span><span class="p">,</span> <span class="mf">0.0</span>

        <span class="n">sample</span> <span class="o">=</span> <span class="n">sample</span> <span class="o">/</span> <span class="n">norm</span>
        <span class="n">template</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="n">templates</span><span class="p">[</span><span class="n">user_id</span><span class="p">]</span>
        <span class="n">distance</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">linalg</span><span class="p">.</span><span class="nf">norm</span><span class="p">(</span><span class="n">template</span> <span class="o">-</span> <span class="n">sample</span><span class="p">)</span>
        <span class="n">score</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">/</span> <span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="n">distance</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">score</span> <span class="o">&gt;=</span> <span class="n">self</span><span class="p">.</span><span class="n">threshold</span><span class="p">,</span> <span class="n">score</span>

<span class="n">matcher</span> <span class="o">=</span> <span class="nc">BiometricMatcher</span><span class="p">(</span><span class="n">threshold</span><span class="o">=</span><span class="mf">0.80</span><span class="p">)</span>
<span class="n">matcher</span><span class="p">.</span><span class="nf">enroll</span><span class="p">(</span><span class="sh">"</span><span class="s">kullanici_42</span><span class="sh">"</span><span class="p">,</span> <span class="p">[</span><span class="mf">0.12</span><span class="p">,</span> <span class="mf">0.77</span><span class="p">,</span> <span class="mf">0.31</span><span class="p">,</span> <span class="mf">0.55</span><span class="p">,</span> <span class="mf">0.18</span><span class="p">])</span>

<span class="n">accepted</span><span class="p">,</span> <span class="n">score</span> <span class="o">=</span> <span class="n">matcher</span><span class="p">.</span><span class="nf">verify</span><span class="p">(</span>
    <span class="sh">"</span><span class="s">kullanici_42</span><span class="sh">"</span><span class="p">,</span>
    <span class="p">[</span><span class="mf">0.11</span><span class="p">,</span> <span class="mf">0.75</span><span class="p">,</span> <span class="mf">0.34</span><span class="p">,</span> <span class="mf">0.53</span><span class="p">,</span> <span class="mf">0.20</span><span class="p">]</span>
<span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">Kabul: </span><span class="si">{</span><span class="n">accepted</span><span class="si">}</span><span class="s">, skor: </span><span class="si">{</span><span class="n">score</span><span class="si">:</span><span class="p">.</span><span class="mi">3</span><span class="n">f</span><span class="si">}</span><span class="sh">"</span><span class="p">)</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">enroll</code> metodu özellik vektörünü normalize ederek saklar. <code class="language-plaintext highlighter-rouge">verify</code> ise yeni örnekle kayıtlı şablonun uzaklığını hesaplar. Normalizasyon, ölçüm ölçeğindeki farklılıkların etkisini azaltır; fakat gerçek sistemlerde dönüş, konum ve sensör kalitesi için çok daha gelişmiş işlemler gerekir.</p>

<h2 id="başarıyı-nasıl-değerlendirebiliriz">Başarıyı nasıl değerlendirebiliriz?</h2>

<p>Sistemi yalnızca “çalıştı” diyerek değerlendirmek yeterli değildir. <strong>FAR</strong> yetkisiz örneklerin kabul oranını, <strong>FRR</strong> ise gerçek kullanıcıların reddedilme oranını gösterir:</p>

\[FAR=\frac{yanlış\ kabuller}{yetkisiz\ denemeler}\]

\[FRR=\frac{yanlış\ retler}{gerçek\ kullanıcı\ denemeleri}\]

<p>Eşiği farklı değerlerde deneyerek bu iki metriği karşılaştırabiliriz. Ayrıca farklı sensör koşulları, gürültü seviyeleri ve kullanıcı gruplarıyla test yapmak olası yanlılıkları ortaya çıkarır.</p>

<p>Son olarak biyometrik veri parola gibi kolayca değiştirilemez. Bu nedenle ham görüntü saklamak yerine şifrelenmiş veya iptal edilebilir şablonlar kullanılmalı; açık rıza, veri minimizasyonu, erişim kontrolü ve silme politikaları tasarımın merkezinde olmalıdır. Küçük dedektifimiz zeki olabilir, ama aynı zamanda mahremiyete saygılı olmak zorundadır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Proje" /><category term="biyometri" /><category term="örüntü tanıma" /><category term="Python" /><summary type="html"><![CDATA[Telefonun kilidini parmağınla açarken cihazın içinde minik bir dedektif çalışır: Görüntüyü temizler, ayırt edici özellikleri çıkarır ve bunları kayıtlı şablonla karşılaştırır. Bu projede gerçek kişisel veriler toplamadan, parmak izi veya iris verisini temsil eden yapay özellik vektörleriyle temel bir biyometrik eşleştirme sisteminin mantığını inceleyeceğiz.]]></summary></entry><entry><title type="html">Kütüphanesiz Yapay Sinir Ağıyla El Yazısı Rakamları Tanıma</title><link href="https://sonsuzus.github.io/posts/kutuphanesiz-yapay-sinir-agiyla-el-yazisi-rakamlari-tanima/" rel="alternate" type="text/html" title="Kütüphanesiz Yapay Sinir Ağıyla El Yazısı Rakamları Tanıma" /><published>2026-08-07T00:00:00+00:00</published><updated>2026-08-07T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/kutuphanesiz-yapay-sinir-agiyla-el-yazisi-rakamlari-tanima</id><content type="html" xml:base="https://sonsuzus.github.io/posts/kutuphanesiz-yapay-sinir-agiyla-el-yazisi-rakamlari-tanima/"><![CDATA[<p>Bir yapay sinir ağının gerçekten nasıl öğrendiğini anlamanın en iyi yolu, hazır makine öğrenmesi kütüphanelerini bir kenara bırakıp bütün parçaları kendimiz yazmaktır. Bu projede yalnızca Python dilinin temel özelliklerini kullanarak MNIST benzeri el yazısı rakamlarını tanıyan, girişten çıkışa ve hatadan geriye doğru öğrenebilen küçük bir sinir ağı geliştireceğiz.</p>

<p>``</p>

<h2 id="problemi-sayılara-dönüştürmek">Problemi sayılara dönüştürmek</h2>

<p>28×28 piksellik gri tonlamalı bir rakam resmi, ağ açısından resim değil, 784 sayıdan oluşan bir vektördür. Her pikseli 255’e bölerek değerleri $[0,1]$ aralığına taşırız:</p>

\[x_i = \frac{piksel_i}{255}\]

<p>Çıkış katmanında ise 10 nöron bulunur. Örneğin doğru cevap 3 ise hedef vektörü $[0,0,0,1,0,0,0,0,0,0]$ olur. Buna <strong>one-hot kodlama</strong> denir.</p>

<table>
  <thead>
    <tr>
      <th>Katman</th>
      <th style="text-align: right">Nöron sayısı</th>
      <th>Görevi</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Giriş</td>
      <td style="text-align: right">784</td>
      <td>Piksel değerlerini almak</td>
    </tr>
    <tr>
      <td>Gizli</td>
      <td style="text-align: right">64</td>
      <td>Çizgi, kıvrım ve kenar örüntülerini öğrenmek</td>
    </tr>
    <tr>
      <td>Çıkış</td>
      <td style="text-align: right">10</td>
      <td>0-9 sınıflarını puanlamak</td>
    </tr>
  </tbody>
</table>

<p>Bir nöron önce ağırlıklı toplam hesaplar:</p>

\[z_j = \sum_i x_i w_{ij} + b_j\]

<p>Ardından doğrusal olmayan sigmoid fonksiyonu uygulanır:</p>

\[\sigma(z)=\frac{1}{1+e^{-z}}\]

<p>Doğrusal olmayan aktivasyon kullanılmazsa çok sayıda katman, matematiksel olarak tek bir doğrusal dönüşüme dönüşür. Başka bir deyişle ağ büyür, fakat zekâsı pek büyümez.</p>

<h2 id="ağı-sıfırdan-kodlamak">Ağı sıfırdan kodlamak</h2>

<p>Aşağıdaki Python kodu matris kütüphanesi kullanmaz. Ağırlıkları üretmek için kendi basit sözde rastgele sayı üretecimizi bile yazıyoruz:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">seed</span> <span class="o">=</span> <span class="mi">123456</span>

<span class="k">def</span> <span class="nf">rnd</span><span class="p">():</span>
    <span class="k">global</span> <span class="n">seed</span>
    <span class="n">seed</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1103515245</span> <span class="o">*</span> <span class="n">seed</span> <span class="o">+</span> <span class="mi">12345</span><span class="p">)</span> <span class="o">%</span> <span class="p">(</span><span class="mi">2</span> <span class="o">**</span> <span class="mi">31</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">seed</span> <span class="o">/</span> <span class="p">(</span><span class="mi">2</span> <span class="o">**</span> <span class="mi">31</span><span class="p">)</span> <span class="o">-</span> <span class="mf">0.5</span>

<span class="k">def</span> <span class="nf">sigmoid</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
    <span class="k">return</span> <span class="mf">1.0</span> <span class="o">/</span> <span class="p">(</span><span class="mf">1.0</span> <span class="o">+</span> <span class="mf">2.718281828</span> <span class="o">**</span> <span class="p">(</span><span class="o">-</span><span class="nf">max</span><span class="p">(</span><span class="o">-</span><span class="mi">30</span><span class="p">,</span> <span class="nf">min</span><span class="p">(</span><span class="mi">30</span><span class="p">,</span> <span class="n">x</span><span class="p">))))</span>

<span class="k">def</span> <span class="nf">matrix</span><span class="p">(</span><span class="n">rows</span><span class="p">,</span> <span class="n">cols</span><span class="p">):</span>
    <span class="k">return</span> <span class="p">[[</span><span class="nf">rnd</span><span class="p">()</span> <span class="o">*</span> <span class="mf">0.1</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">cols</span><span class="p">)]</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">rows</span><span class="p">)]</span>

<span class="n">INPUT</span><span class="p">,</span> <span class="n">HIDDEN</span><span class="p">,</span> <span class="n">OUTPUT</span> <span class="o">=</span> <span class="mi">784</span><span class="p">,</span> <span class="mi">64</span><span class="p">,</span> <span class="mi">10</span>
<span class="n">w1</span> <span class="o">=</span> <span class="nf">matrix</span><span class="p">(</span><span class="n">HIDDEN</span><span class="p">,</span> <span class="n">INPUT</span><span class="p">)</span>
<span class="n">b1</span> <span class="o">=</span> <span class="p">[</span><span class="mf">0.0</span><span class="p">]</span> <span class="o">*</span> <span class="n">HIDDEN</span>
<span class="n">w2</span> <span class="o">=</span> <span class="nf">matrix</span><span class="p">(</span><span class="n">OUTPUT</span><span class="p">,</span> <span class="n">HIDDEN</span><span class="p">)</span>
<span class="n">b2</span> <span class="o">=</span> <span class="p">[</span><span class="mf">0.0</span><span class="p">]</span> <span class="o">*</span> <span class="n">OUTPUT</span>

<span class="k">def</span> <span class="nf">forward</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
    <span class="n">hidden</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">HIDDEN</span><span class="p">):</span>
        <span class="n">z</span> <span class="o">=</span> <span class="n">b1</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">+</span> <span class="nf">sum</span><span class="p">(</span><span class="n">w1</span><span class="p">[</span><span class="n">j</span><span class="p">][</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">x</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">INPUT</span><span class="p">))</span>
        <span class="n">hidden</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="nf">sigmoid</span><span class="p">(</span><span class="n">z</span><span class="p">))</span>

    <span class="n">output</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">OUTPUT</span><span class="p">):</span>
        <span class="n">z</span> <span class="o">=</span> <span class="n">b2</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="nf">sum</span><span class="p">(</span><span class="n">w2</span><span class="p">[</span><span class="n">k</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">hidden</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">HIDDEN</span><span class="p">))</span>
        <span class="n">output</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="nf">sigmoid</span><span class="p">(</span><span class="n">z</span><span class="p">))</span>
    <span class="k">return</span> <span class="n">hidden</span><span class="p">,</span> <span class="n">output</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">forward</code> fonksiyonu tahmin üretir; ancak öğrenme için hatayı ağırlıklara geri dağıtmamız gerekir. Ortalama karesel hata kullanırsak temel hedefimiz şudur:</p>

\[L=\frac{1}{2}\sum_k(y_k-\hat{y}_k)^2\]

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">train</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">target</span><span class="p">,</span> <span class="n">rate</span><span class="o">=</span><span class="mf">0.1</span><span class="p">):</span>
    <span class="n">hidden</span><span class="p">,</span> <span class="n">output</span> <span class="o">=</span> <span class="nf">forward</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>

    <span class="n">out_delta</span> <span class="o">=</span> <span class="p">[</span>
        <span class="p">(</span><span class="n">output</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">-</span> <span class="n">target</span><span class="p">[</span><span class="n">k</span><span class="p">])</span> <span class="o">*</span> <span class="n">output</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">-</span> <span class="n">output</span><span class="p">[</span><span class="n">k</span><span class="p">])</span>
        <span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">OUTPUT</span><span class="p">)</span>
    <span class="p">]</span>

    <span class="n">hid_delta</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">HIDDEN</span><span class="p">):</span>
        <span class="n">error</span> <span class="o">=</span> <span class="nf">sum</span><span class="p">(</span><span class="n">out_delta</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">*</span> <span class="n">w2</span><span class="p">[</span><span class="n">k</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">OUTPUT</span><span class="p">))</span>
        <span class="n">hid_delta</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">error</span> <span class="o">*</span> <span class="n">hidden</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">-</span> <span class="n">hidden</span><span class="p">[</span><span class="n">j</span><span class="p">]))</span>

    <span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">OUTPUT</span><span class="p">):</span>
        <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">HIDDEN</span><span class="p">):</span>
            <span class="n">w2</span><span class="p">[</span><span class="n">k</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">-=</span> <span class="n">rate</span> <span class="o">*</span> <span class="n">out_delta</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">*</span> <span class="n">hidden</span><span class="p">[</span><span class="n">j</span><span class="p">]</span>
        <span class="n">b2</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">-=</span> <span class="n">rate</span> <span class="o">*</span> <span class="n">out_delta</span><span class="p">[</span><span class="n">k</span><span class="p">]</span>

    <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">HIDDEN</span><span class="p">):</span>
        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">INPUT</span><span class="p">):</span>
            <span class="n">w1</span><span class="p">[</span><span class="n">j</span><span class="p">][</span><span class="n">i</span><span class="p">]</span> <span class="o">-=</span> <span class="n">rate</span> <span class="o">*</span> <span class="n">hid_delta</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">x</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
        <span class="n">b1</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">-=</span> <span class="n">rate</span> <span class="o">*</span> <span class="n">hid_delta</span><span class="p">[</span><span class="n">j</span><span class="p">]</span>
</code></pre></div></div>

<h2 id="eğitim-ve-tahmin">Eğitim ve tahmin</h2>

<p>Her eğitim resmi için piksel listesini normalize eder, doğru rakamın hedef değerini 1 yapar ve <code class="language-plaintext highlighter-rouge">train</code> fonksiyonunu çağırırız. Bu işlemin tüm veri üzerinde bir kez yapılmasına <strong>epoch</strong> denir. Eğitimden sonra tahmin, en yüksek çıkış değerinin indeksidir:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">predict</span><span class="p">(</span><span class="n">pixels</span><span class="p">):</span>
    <span class="n">x</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span> <span class="o">/</span> <span class="mf">255.0</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">pixels</span><span class="p">]</span>
    <span class="n">_</span><span class="p">,</span> <span class="n">scores</span> <span class="o">=</span> <span class="nf">forward</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
    <span class="k">return</span> <span class="nf">max</span><span class="p">(</span><span class="nf">range</span><span class="p">(</span><span class="mi">10</span><span class="p">),</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">i</span><span class="p">:</span> <span class="n">scores</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
</code></pre></div></div>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Avantaj</th>
      <th>Dezavantaj</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Sıfırdan ağ</td>
      <td>Matematiği görünür kılar</td>
      <td>Yavaş çalışır</td>
    </tr>
    <tr>
      <td>Hazır kütüphane</td>
      <td>Hızlı ve optimize</td>
      <td>Ayrıntıları gizleyebilir</td>
    </tr>
  </tbody>
</table>

<p>Bu ağ modern modellerle yarışmayacaktır; fakat ileri yayılım, geri yayılım, gradyan inişi ve sınıflandırmanın nasıl birleştiğini açıkça gösterir. Sonraki adım olarak mini-batch eğitimi, ReLU, softmax ve çapraz entropi eklenebilir. Artık sinir ağı gizemli bir kara kutu değil; bolca döngü, türev ve sabırdan oluşan anlaşılır bir makinedir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Proje" /><category term="yapay sinir ağı" /><category term="Python" /><category term="MNIST" /><summary type="html"><![CDATA[Bir yapay sinir ağının gerçekten nasıl öğrendiğini anlamanın en iyi yolu, hazır makine öğrenmesi kütüphanelerini bir kenara bırakıp bütün parçaları kendimiz yazmaktır. Bu projede yalnızca Python dilinin temel özelliklerini kullanarak MNIST benzeri el yazısı rakamlarını tanıyan, girişten çıkışa ve hatadan geriye doğru öğrenebilen küçük bir sinir ağı geliştireceğiz.]]></summary></entry><entry><title type="html">Parçacıklardan Akışkanlara: Gerçek Zamanlı Su, Ateş ve Duman Simülasyonu</title><link href="https://sonsuzus.github.io/posts/parcaciklardan-akiskanlara-gercek-zamanli-su-ates-ve-duman-simulasyonu/" rel="alternate" type="text/html" title="Parçacıklardan Akışkanlara: Gerçek Zamanlı Su, Ateş ve Duman Simülasyonu" /><published>2026-08-07T00:00:00+00:00</published><updated>2026-08-07T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/parcaciklardan-akiskanlara-gercek-zamanli-su-ates-ve-duman-simulasyonu</id><content type="html" xml:base="https://sonsuzus.github.io/posts/parcaciklardan-akiskanlara-gercek-zamanli-su-ates-ve-duman-simulasyonu/"><![CDATA[<p>Bir avuç noktanın su gibi akmasını, ateş gibi yükselmesini veya duman gibi havada süzülmesini sağlamak ilk bakışta büyücülük gibi görünebilir. Oysa gerçek zamanlı akışkan simülasyonlarının temelinde parçacıklar, kuvvetler ve her karede tekrarlanan birkaç fizik hesabı bulunur. Tam ölçekli bilimsel doğruluk yerine görsel inandırıcılığı hedefleyerek tarayıcıda bile çalışan eğlenceli bir mini fizik motoru geliştirebiliriz.
``</p>
<h2 id="temel-fikir-her-damla-bir-parçacık">Temel fikir: Her damla bir parçacık</h2>

<p>Parçacık sistemi, akışkanı çok sayıda küçük nesneyle temsil eder. Her parçacığın konumu $\vec{x}$, hızı $\vec{v}$, kütlesi $m$, ömrü ve türüne özgü özellikleri bulunur. Simülasyon döngüsünde önce kuvvetler hesaplanır, ardından ivme, hız ve konum güncellenir.</p>

<p>Newton’un ikinci yasası başlangıç noktamızdır:</p>

\[\vec{F}=m\vec{a} \quad \Rightarrow \quad \vec{a}=\frac{\vec{F}}{m}\]

<p>Basit Euler integrasyonuyla güncelleme şöyledir:</p>

\[\vec{v}_{t+\Delta t}=\vec{v}_t+\vec{a}\Delta t\]

\[\vec{x}_{t+\Delta t}=\vec{x}_t+\vec{v}_{t+\Delta t}\Delta t\]

<p>Buradaki $\Delta t$, iki kare arasında geçen süredir. Sabit zaman adımı kullanmak simülasyonun farklı ekran yenileme hızlarında benzer davranmasını sağlar.</p>

<h2 id="su-ateş-ve-duman-neden-farklı-görünür">Su, ateş ve duman neden farklı görünür?</h2>

<p>Aynı motoru kullanıp kuvvetleri ve görsel özellikleri değiştirerek üç farklı akışkan izlenimi oluşturabiliriz.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Su</th>
      <th>Ateş</th>
      <th>Duman</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Ana kuvvet</td>
      <td>Aşağı yönlü yerçekimi</td>
      <td>Yukarı yönlü kaldırma</td>
      <td>Zayıf kaldırma ve rüzgâr</td>
    </tr>
    <tr>
      <td>Parçacık ömrü</td>
      <td>Uzun</td>
      <td>Kısa</td>
      <td>Orta veya uzun</td>
    </tr>
    <tr>
      <td>Hareket</td>
      <td>Yoğun ve yapışkan</td>
      <td>Hızlı ve titreşimli</td>
      <td>Yavaş ve dağınık</td>
    </tr>
    <tr>
      <td>Görünüm</td>
      <td>Mavi, yüksek opaklık</td>
      <td>Sarıdan kırmızıya</td>
      <td>Gri, giderek saydam</td>
    </tr>
    <tr>
      <td>Çarpışma</td>
      <td>Zemin ve kaplarla önemli</td>
      <td>Genellikle gereksiz</td>
      <td>Genellikle gereksiz</td>
    </tr>
  </tbody>
</table>

<p>Su için yerçekimi, yüzey çarpışmaları ve komşu parçacıklar arasında itme kuvveti gerekir. Basitleştirilmiş basınç kuvveti, iki parçacık arasındaki uzaklık $r$ etkileşim yarıçapı $h$ değerinden küçükse uygulanabilir:</p>

\[F_p=k(h-r)\]

<p>Burada $k$, akışkanın ne kadar sıkışmaz görüneceğini belirleyen katsayıdır. Bu yaklaşım gerçek SPH yönteminin sadeleştirilmiş hâlidir; bilimsel olarak kusursuz değildir ama oyun efektleri için hızlıdır.</p>

<p>Ateşte negatif yerçekimi benzeri bir kaldırma kuvveti kullanılır. Parçacık yaşlandıkça boyutu büyütülür, rengi sarıdan turuncuya geçirilir ve opaklığı azaltılır. Duman da yükselir fakat rastgele rüzgâr kuvvetleriyle yatayda daha fazla savrulur.</p>

<h2 id="javascript-ile-çekirdek-parçacık-sınıfı">JavaScript ile çekirdek parçacık sınıfı</h2>

<p>Aşağıdaki sınıf kuvvet biriktirme, Euler integrasyonu ve yaşam süresi yönetimini gerçekleştirir:</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">Particle</span> <span class="p">{</span>
  <span class="nf">constructor</span><span class="p">(</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">,</span> <span class="nx">type</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="nx">x</span><span class="p">;</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">y</span> <span class="o">=</span> <span class="nx">y</span><span class="p">;</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">vx</span> <span class="o">=</span> <span class="p">(</span><span class="nb">Math</span><span class="p">.</span><span class="nf">random</span><span class="p">()</span> <span class="o">-</span> <span class="mf">0.5</span><span class="p">)</span> <span class="o">*</span> <span class="mi">40</span><span class="p">;</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">vy</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">ax</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">ay</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">age</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">life</span> <span class="o">=</span> <span class="nx">type</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">fire</span><span class="dl">'</span> <span class="p">?</span> <span class="mf">1.2</span> <span class="p">:</span> <span class="mi">3</span><span class="p">;</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">type</span> <span class="o">=</span> <span class="nx">type</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="nf">applyForce</span><span class="p">(</span><span class="nx">fx</span><span class="p">,</span> <span class="nx">fy</span><span class="p">,</span> <span class="nx">mass</span> <span class="o">=</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">ax</span> <span class="o">+=</span> <span class="nx">fx</span> <span class="o">/</span> <span class="nx">mass</span><span class="p">;</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">ay</span> <span class="o">+=</span> <span class="nx">fy</span> <span class="o">/</span> <span class="nx">mass</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="nf">update</span><span class="p">(</span><span class="nx">dt</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">gravity</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">type</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">water</span><span class="dl">'</span> <span class="p">?</span> <span class="mi">500</span> <span class="p">:</span> <span class="o">-</span><span class="mi">80</span><span class="p">;</span>
    <span class="kd">const</span> <span class="nx">turbulence</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">type</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">water</span><span class="dl">'</span>
      <span class="p">?</span> <span class="mi">0</span>
      <span class="p">:</span> <span class="p">(</span><span class="nb">Math</span><span class="p">.</span><span class="nf">random</span><span class="p">()</span> <span class="o">-</span> <span class="mf">0.5</span><span class="p">)</span> <span class="o">*</span> <span class="mi">100</span><span class="p">;</span>

    <span class="k">this</span><span class="p">.</span><span class="nf">applyForce</span><span class="p">(</span><span class="nx">turbulence</span><span class="p">,</span> <span class="nx">gravity</span><span class="p">);</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">vx</span> <span class="o">+=</span> <span class="k">this</span><span class="p">.</span><span class="nx">ax</span> <span class="o">*</span> <span class="nx">dt</span><span class="p">;</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">vy</span> <span class="o">+=</span> <span class="k">this</span><span class="p">.</span><span class="nx">ay</span> <span class="o">*</span> <span class="nx">dt</span><span class="p">;</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">+=</span> <span class="k">this</span><span class="p">.</span><span class="nx">vx</span> <span class="o">*</span> <span class="nx">dt</span><span class="p">;</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">y</span> <span class="o">+=</span> <span class="k">this</span><span class="p">.</span><span class="nx">vy</span> <span class="o">*</span> <span class="nx">dt</span><span class="p">;</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">ax</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">ay</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">age</span> <span class="o">+=</span> <span class="nx">dt</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="kd">get</span> <span class="nf">alive</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">age</span> <span class="o">&lt;</span> <span class="k">this</span><span class="p">.</span><span class="nx">life</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Her animasyon karesinde parçacıklara kuvvet uygulanır, <code class="language-plaintext highlighter-rouge">update(dt)</code> çağrılır ve ömrü dolanlar diziden çıkarılır. Su parçacıkları zemine çarptığında <code class="language-plaintext highlighter-rouge">vy *= -0.3</code> ile sönümlü sekme uygulanabilir. Daha yapışkan bir sonuç için yatay hız da <code class="language-plaintext highlighter-rouge">vx *= 0.9</code> ile azaltılabilir.</p>

<h2 id="performans-ve-görsel-sihir">Performans ve görsel sihir</h2>

<p>Parçacık sayısı yükseldiğinde bütün parçacık çiftlerini karşılaştırmak $O(n^2)$ maliyet oluşturur. Alanı ızgara hücrelerine bölerek yalnızca yakın hücrelerdeki komşuları test etmek maliyeti büyük ölçüde azaltır. Canvas üzerinde daire çizmek başlangıç için yeterlidir; WebGL kullanıldığında binlerce parçacık GPU üzerinde işlenebilir.</p>

<p>Son dokunuş fizik değil, sunumdur: suya yarı saydam katmanlar, ateşe additive blending, dumana yumuşak dokular ekleyin. Böylece basit denklemler, doğru renk ve hareket tercihleriyle şaşırtıcı derecede canlı bir akışkan gösterisine dönüşür.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Proje" /><category term="parçacık sistemi" /><category term="fizik motoru" /><category term="akışkan simülasyonu" /><summary type="html"><![CDATA[Bir avuç noktanın su gibi akmasını, ateş gibi yükselmesini veya duman gibi havada süzülmesini sağlamak ilk bakışta büyücülük gibi görünebilir. Oysa gerçek zamanlı akışkan simülasyonlarının temelinde parçacıklar, kuvvetler ve her karede tekrarlanan birkaç fizik hesabı bulunur. Tam ölçekli bilimsel doğruluk yerine görsel inandırıcılığı hedefleyerek tarayıcıda bile çalışan eğlenceli bir mini fizik motoru geliştirebiliriz.]]></summary></entry><entry><title type="html">Parolaları Güvenle Saklamak ve XSS Açıklarını Kapatmak</title><link href="https://sonsuzus.github.io/posts/parolalari-guvenle-saklamak-ve-xss-aciklarini-kapatmak/" rel="alternate" type="text/html" title="Parolaları Güvenle Saklamak ve XSS Açıklarını Kapatmak" /><published>2026-08-07T00:00:00+00:00</published><updated>2026-08-07T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/parolalari-guvenle-saklamak-ve-xss-aciklarini-kapatmak</id><content type="html" xml:base="https://sonsuzus.github.io/posts/parolalari-guvenle-saklamak-ve-xss-aciklarini-kapatmak/"><![CDATA[<p>Bir web uygulamasında güvenlik, kapıya pahalı bir kilit takıp anahtarı paspasın altında bırakmamaktır. Kullanıcı parolalarını düz metin olarak saklamak tam da böyle bir hatadır. Veritabanı sızdırıldığında saldırganlar yalnızca uygulamadaki hesaplara değil, parola tekrar kullanılmışsa başka servislere de erişebilir. Benzer şekilde XSS açıkları, güvenilmeyen içeriğin tarayıcıda kod gibi çalışmasına izin vererek kullanıcı oturumlarını ve verilerini tehlikeye atar.
``</p>
<h2 id="şifreleme-ile-hashleme-aynı-şey-değildir">Şifreleme ile hashleme aynı şey değildir</h2>

<p>Şifreleme, doğru anahtara sahip olan kişinin veriyi geri çözebilmesi için tasarlanmıştır. Parolalarda ise uygulamanın özgün metni öğrenmesine gerek yoktur. Bu nedenle parola <strong>şifrelenmemeli</strong>, tek yönlü bir parola türetme fonksiyonuyla hashlenmelidir.</p>

<table>
  <thead>
    <tr>
      <th>Yöntem</th>
      <th style="text-align: right">Geri döndürülebilir mi?</th>
      <th style="text-align: right">Parola saklamaya uygun mu?</th>
      <th>Örnek</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Düz metin</td>
      <td style="text-align: right">Zaten okunabilir</td>
      <td style="text-align: right">Hayır</td>
      <td><code class="language-plaintext highlighter-rouge">deneme123</code></td>
    </tr>
    <tr>
      <td>Şifreleme</td>
      <td style="text-align: right">Anahtarla evet</td>
      <td style="text-align: right">Genellikle hayır</td>
      <td>AES-GCM</td>
    </tr>
    <tr>
      <td>Hızlı hash</td>
      <td style="text-align: right">Pratikte hayır</td>
      <td style="text-align: right">Hayır</td>
      <td>SHA-256</td>
    </tr>
    <tr>
      <td>Parola hashleme</td>
      <td style="text-align: right">Pratikte hayır</td>
      <td style="text-align: right">Evet</td>
      <td>Argon2id, scrypt, bcrypt</td>
    </tr>
  </tbody>
</table>

<p>SHA-256 kriptografik olarak güçlü olsa da çok hızlıdır. Saldırganların saniyede milyonlarca parola tahmini yapabilmesi burada avantaj değil, felakettir. Argon2id gibi algoritmalar zaman ve bellek maliyetini yükselterek tahmin saldırılarını pahalılaştırır.</p>

<p>Bir parola $P$, rastgele salt $S$ ve maliyet parametreleri $m$, $t$, $p$ ile şöyle işlenebilir:</p>

\[H = \operatorname{Argon2id}(P, S, m, t, p)\]

<p><strong>Salt</strong>, her kullanıcı için rastgele üretilir ve hash ile birlikte saklanabilir. Böylece aynı parolayı seçen iki kullanıcının hashleri farklı olur; hazır gökkuşağı tabloları da etkisizleşir.</p>

<h2 id="nodejs-ile-güvenli-parola-işleme">Node.js ile güvenli parola işleme</h2>

<p>Aşağıdaki örnek, <code class="language-plaintext highlighter-rouge">argon2</code> paketiyle hash üretir ve giriş sırasında doğrulama yapar:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="nx">argon2</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">argon2</span><span class="dl">"</span><span class="p">;</span>

<span class="k">export</span> <span class="k">async</span> <span class="kd">function</span> <span class="nf">createPasswordHash</span><span class="p">(</span><span class="nx">password</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">return</span> <span class="nx">argon2</span><span class="p">.</span><span class="nf">hash</span><span class="p">(</span><span class="nx">password</span><span class="p">,</span> <span class="p">{</span>
    <span class="na">type</span><span class="p">:</span> <span class="nx">argon2</span><span class="p">.</span><span class="nx">argon2id</span><span class="p">,</span>
    <span class="na">memoryCost</span><span class="p">:</span> <span class="mi">19456</span><span class="p">,</span>
    <span class="na">timeCost</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
    <span class="na">parallelism</span><span class="p">:</span> <span class="mi">1</span>
  <span class="p">});</span>
<span class="p">}</span>

<span class="k">export</span> <span class="k">async</span> <span class="kd">function</span> <span class="nf">verifyPassword</span><span class="p">(</span><span class="nx">storedHash</span><span class="p">,</span> <span class="nx">candidate</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">return</span> <span class="nx">argon2</span><span class="p">.</span><span class="nf">verify</span><span class="p">(</span><span class="nx">storedHash</span><span class="p">,</span> <span class="nx">candidate</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Üretilen değer salt ve algoritma parametrelerini de taşır. Veritabanına parola yerine bu çıktı kaydedilir. Parametreler sunucunun kapasitesine göre ölçülmeli; giriş işlemini kabul edilebilir düzeyde tutarken toplu tahminleri yavaşlatmalıdır. Ayrıca giriş uç noktalarına hız sınırlama ve çok faktörlü kimlik doğrulama eklenmelidir.</p>

<h2 id="xss-nasıl-ortaya-çıkar">XSS nasıl ortaya çıkar?</h2>

<p>XSS, kullanıcı girdisinin HTML veya JavaScript olarak yorumlanmasıdır. Örneğin bir yorum doğrudan <code class="language-plaintext highlighter-rouge">innerHTML</code> ile sayfaya basılırsa saldırgan <code class="language-plaintext highlighter-rouge">&lt;script&gt;</code> etiketi ya da olay işleyicisi enjekte edebilir.</p>

<table>
  <thead>
    <tr>
      <th>Riskli yaklaşım</th>
      <th>Güvenli yaklaşım</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">element.innerHTML = input</code></td>
      <td><code class="language-plaintext highlighter-rouge">element.textContent = input</code></td>
    </tr>
    <tr>
      <td>Elle karakter değiştirme</td>
      <td>Bağlama duyarlı çıktı kodlama</td>
    </tr>
    <tr>
      <td>Her HTML etiketine izin verme</td>
      <td>Güvenilir kütüphaneyle sanitizasyon</td>
    </tr>
    <tr>
      <td>Satır içi script kullanma</td>
      <td>CSP ve harici script dosyaları</td>
    </tr>
  </tbody>
</table>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">message</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nf">querySelector</span><span class="p">(</span><span class="dl">"</span><span class="s2">#message</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">message</span><span class="p">.</span><span class="nx">textContent</span> <span class="o">=</span> <span class="nx">userInput</span><span class="p">;</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">textContent</code>, girdiyi çalıştırılabilir HTML yerine metin olarak ekler. Zengin HTML kabul edilmesi gerçekten gerekiyorsa DOMPurify gibi bakımı sürdürülen bir sanitizasyon kütüphanesi kullanılmalıdır. URL, HTML niteliği, JavaScript ve CSS bağlamlarının farklı kodlama kuralları olduğu unutulmamalıdır.</p>

<p>Ek savunma olarak sunucu bir Content Security Policy gönderebilir:</p>

<div class="language-http highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'
</span></code></pre></div></div>

<p>CSP tek başına açığı düzeltmez; başarılı bir enjeksiyonun etkisini sınırlar. Güvenli şablon motorları, <code class="language-plaintext highlighter-rouge">HttpOnly</code>, <code class="language-plaintext highlighter-rouge">Secure</code> ve <code class="language-plaintext highlighter-rouge">SameSite</code> çerezleri de savunmayı katmanlandırır. Özetle parolalarda Argon2id gibi yavaş hash fonksiyonları, XSS tarafında bağlama uygun kodlama, sanitizasyon ve CSP birlikte kullanılmalıdır. Güvenlik tek bir sihirli fonksiyon değil, birbirini tamamlayan kontrollere dayanan bir süreçtir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="web güvenliği" /><category term="parola hashleme" /><category term="XSS" /><summary type="html"><![CDATA[Bir web uygulamasında güvenlik, kapıya pahalı bir kilit takıp anahtarı paspasın altında bırakmamaktır. Kullanıcı parolalarını düz metin olarak saklamak tam da böyle bir hatadır. Veritabanı sızdırıldığında saldırganlar yalnızca uygulamadaki hesaplara değil, parola tekrar kullanılmışsa başka servislere de erişebilir. Benzer şekilde XSS açıkları, güvenilmeyen içeriğin tarayıcıda kod gibi çalışmasına izin vererek kullanıcı oturumlarını ve verilerini tehlikeye atar.]]></summary></entry><entry><title type="html">PHP ile RESTful API Temelleri: Uygulamanızı JSON Köprüsüne Dönüştürün</title><link href="https://sonsuzus.github.io/posts/php-ile-restful-api-temelleri-uygulamanizi-json-koprusune-donusturun/" rel="alternate" type="text/html" title="PHP ile RESTful API Temelleri: Uygulamanızı JSON Köprüsüne Dönüştürün" /><published>2026-08-07T00:00:00+00:00</published><updated>2026-08-07T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/php-ile-restful-api-temelleri-uygulamanizi-json-koprusune-donusturun</id><content type="html" xml:base="https://sonsuzus.github.io/posts/php-ile-restful-api-temelleri-uygulamanizi-json-koprusune-donusturun/"><![CDATA[<p>Bir PHP uygulaması yalnızca HTML üretmek zorunda değildir. Aynı uygulama; mobil istemcilere, JavaScript arayüzlerine ve başka sunuculara dinamik veri sağlayan bir API olarak da çalışabilir. Bunun anahtarı, kaynakları HTTP üzerinden anlaşılır biçimde sunmak ve yanıtları ortak bir veri formatı olan JSON ile iletmektir.
``</p>
<h2 id="rest-nedir">REST nedir?</h2>

<p>REST, yani <strong>Representational State Transfer</strong>, katı bir protokolden çok web servisleri tasarlamak için kullanılan mimari ilkeler bütünüdür. Temel fikir şudur: Sistemdeki kullanıcı, ürün veya sipariş gibi varlıklar birer <strong>kaynak</strong> olarak ele alınır. Her kaynak bir URL ile temsil edilir ve kaynak üzerinde yapılacak işlem HTTP metodu tarafından belirtilir.</p>

<p>Örneğin <code class="language-plaintext highlighter-rouge">/api/products/12</code> adresi, kimliği 12 olan ürünü temsil edebilir. URL’nin <code class="language-plaintext highlighter-rouge">urun-getir.php?id=12</code> gibi bir eylem anlatması yerine kaynağı tanımlaması REST yaklaşımına daha uygundur.</p>

<table>
  <thead>
    <tr>
      <th>HTTP metodu</th>
      <th>Amaç</th>
      <th>Örnek adres</th>
      <th>Olası durum kodu</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">GET</code></td>
      <td>Kaynak okumak</td>
      <td><code class="language-plaintext highlighter-rouge">/api/products/12</code></td>
      <td><code class="language-plaintext highlighter-rouge">200 OK</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">POST</code></td>
      <td>Yeni kaynak oluşturmak</td>
      <td><code class="language-plaintext highlighter-rouge">/api/products</code></td>
      <td><code class="language-plaintext highlighter-rouge">201 Created</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">PUT</code></td>
      <td>Kaynağı bütünüyle güncellemek</td>
      <td><code class="language-plaintext highlighter-rouge">/api/products/12</code></td>
      <td><code class="language-plaintext highlighter-rouge">200 OK</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">PATCH</code></td>
      <td>Kısmi güncelleme yapmak</td>
      <td><code class="language-plaintext highlighter-rouge">/api/products/12</code></td>
      <td><code class="language-plaintext highlighter-rouge">200 OK</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">DELETE</code></td>
      <td>Kaynağı silmek</td>
      <td><code class="language-plaintext highlighter-rouge">/api/products/12</code></td>
      <td><code class="language-plaintext highlighter-rouge">204 No Content</code></td>
    </tr>
  </tbody>
</table>

<p>REST servislerinin <strong>durumsuz</strong> olması beklenir. Sunucu, önceki isteği hatırlamak zorunda kalmamalıdır; ihtiyaç duyulan kimlik doğrulama ve parametreler her istekte taşınmalıdır. Böylece istek sayısı $n$ olduğunda işlemler birbirinden bağımsız kalır ve sistemin yatay olarak ölçeklenmesi kolaylaşır.</p>

<h2 id="json-neden-kullanılır">JSON neden kullanılır?</h2>

<p>JSON, anahtar-değer çiftlerinden ve dizilerden oluşan hafif bir veri formatıdır. PHP dizileri, JavaScript nesneleri ve pek çok dildeki sözlük yapılarıyla rahatça eşleştirilebilir.</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">12</span><span class="p">,</span><span class="w">
  </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Mekanik Klavye"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"price"</span><span class="p">:</span><span class="w"> </span><span class="mf">2499.90</span><span class="p">,</span><span class="w">
  </span><span class="nl">"inStock"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>JSON yalnızca veriyi taşır; görünüm kararını istemciye bırakır. Aynı yanıt mobil uygulamada kart, yönetim panelinde tablo, başka bir sistemde ise rapor satırı olarak gösterilebilir. Yaklaşık yanıt boyutu $B$ ve saniyedeki istek sayısı $R$ ise ağ yükü kabaca $B \times R$ ile ifade edilebilir. Gereksiz alanları kaldırmak bu nedenle önemlidir.</p>

<h2 id="php-ile-basit-bir-api-uç-noktası">PHP ile basit bir API uç noktası</h2>

<p>Aşağıdaki örnek, PDO kullanarak veritabanından ürünleri okur ve JSON yanıtı döndürür:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
<span class="nb">header</span><span class="p">(</span><span class="s1">'Content-Type: application/json; charset=utf-8'</span><span class="p">);</span>

<span class="nv">$pdo</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">PDO</span><span class="p">(</span>
    <span class="s1">'mysql:host=localhost;dbname=shop;charset=utf8mb4'</span><span class="p">,</span>
    <span class="s1">'api_user'</span><span class="p">,</span>
    <span class="s1">'secret'</span><span class="p">,</span>
    <span class="p">[</span><span class="no">PDO</span><span class="o">::</span><span class="no">ATTR_ERRMODE</span> <span class="o">=&gt;</span> <span class="no">PDO</span><span class="o">::</span><span class="no">ERRMODE_EXCEPTION</span><span class="p">]</span>
<span class="p">);</span>

<span class="k">try</span> <span class="p">{</span>
    <span class="nv">$stmt</span> <span class="o">=</span> <span class="nv">$pdo</span><span class="o">-&gt;</span><span class="nf">query</span><span class="p">(</span>
        <span class="s1">'SELECT id, name, price FROM products ORDER BY id DESC'</span>
    <span class="p">);</span>

    <span class="nv">$products</span> <span class="o">=</span> <span class="nv">$stmt</span><span class="o">-&gt;</span><span class="nf">fetchAll</span><span class="p">(</span><span class="no">PDO</span><span class="o">::</span><span class="no">FETCH_ASSOC</span><span class="p">);</span>

    <span class="nb">http_response_code</span><span class="p">(</span><span class="mi">200</span><span class="p">);</span>
    <span class="k">echo</span> <span class="nb">json_encode</span><span class="p">([</span>
        <span class="s1">'success'</span> <span class="o">=&gt;</span> <span class="kc">true</span><span class="p">,</span>
        <span class="s1">'data'</span> <span class="o">=&gt;</span> <span class="nv">$products</span><span class="p">,</span>
        <span class="s1">'count'</span> <span class="o">=&gt;</span> <span class="nb">count</span><span class="p">(</span><span class="nv">$products</span><span class="p">)</span>
    <span class="p">],</span> <span class="no">JSON_UNESCAPED_UNICODE</span> <span class="o">|</span> <span class="no">JSON_PRESERVE_ZERO_FRACTION</span><span class="p">);</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nc">Throwable</span> <span class="nv">$error</span><span class="p">)</span> <span class="p">{</span>
    <span class="nb">http_response_code</span><span class="p">(</span><span class="mi">500</span><span class="p">);</span>
    <span class="k">echo</span> <span class="nb">json_encode</span><span class="p">([</span>
        <span class="s1">'success'</span> <span class="o">=&gt;</span> <span class="kc">false</span><span class="p">,</span>
        <span class="s1">'error'</span> <span class="o">=&gt;</span> <span class="s1">'Sunucu hatası oluştu.'</span>
    <span class="p">],</span> <span class="no">JSON_UNESCAPED_UNICODE</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">Content-Type</code> başlığı istemciye yanıtın JSON olduğunu bildirir. <code class="language-plaintext highlighter-rouge">json_encode()</code> PHP dizisini JSON metnine dönüştürür. Hata oluştuğunda ayrıntılı veritabanı mesajını dışarı vermemek ise tablo adları veya bağlantı bilgileri gibi hassas ayrıntıların sızmasını önler.</p>

<h2 id="i̇stek-gövdesini-okumak">İstek gövdesini okumak</h2>

<p><code class="language-plaintext highlighter-rouge">POST</code> ve <code class="language-plaintext highlighter-rouge">PATCH</code> isteklerinde JSON verisi <code class="language-plaintext highlighter-rouge">php://input</code> üzerinden alınabilir:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$body</span> <span class="o">=</span> <span class="nb">file_get_contents</span><span class="p">(</span><span class="s1">'php://input'</span><span class="p">);</span>
<span class="nv">$input</span> <span class="o">=</span> <span class="nb">json_decode</span><span class="p">(</span><span class="nv">$body</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>

<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nb">is_array</span><span class="p">(</span><span class="nv">$input</span><span class="p">)</span> <span class="o">||</span> <span class="k">empty</span><span class="p">(</span><span class="nv">$input</span><span class="p">[</span><span class="s1">'name'</span><span class="p">]))</span> <span class="p">{</span>
    <span class="nb">http_response_code</span><span class="p">(</span><span class="mi">422</span><span class="p">);</span>
    <span class="k">echo</span> <span class="nb">json_encode</span><span class="p">([</span><span class="s1">'error'</span> <span class="o">=&gt;</span> <span class="s1">'name alanı zorunludur.'</span><span class="p">]);</span>
    <span class="k">exit</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">422 Unprocessable Content</code>, JSON okunabilse bile doğrulama kurallarının sağlanmadığını anlatır. Geçersiz JSON için <code class="language-plaintext highlighter-rouge">400 Bad Request</code>, bulunamayan kaynak için <code class="language-plaintext highlighter-rouge">404 Not Found</code> kullanılmalıdır. Her hataya <code class="language-plaintext highlighter-rouge">200</code> dönmek, yangın alarmını ne olursa olsun yeşil yakmaya benzer!</p>

<p>Son olarak API’yi HTTPS, token tabanlı kimlik doğrulama, giriş doğrulama, hız sınırlama ve sürümleme ile güçlendirin. <code class="language-plaintext highlighter-rouge">/api/v1/products</code> gibi sürümlü adresler, gelecekte yapılacak değişikliklerin mevcut istemcileri bozmamasına yardımcı olur. Böylece PHP uygulamanız bir web sayfası üreticisinden, farklı sistemlerin güvenle konuşabildiği gerçek bir veri köprüsüne dönüşür.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="PHP" /><category term="REST API" /><category term="JSON" /><summary type="html"><![CDATA[Bir PHP uygulaması yalnızca HTML üretmek zorunda değildir. Aynı uygulama; mobil istemcilere, JavaScript arayüzlerine ve başka sunuculara dinamik veri sağlayan bir API olarak da çalışabilir. Bunun anahtarı, kaynakları HTTP üzerinden anlaşılır biçimde sunmak ve yanıtları ortak bir veri formatı olan JSON ile iletmektir.]]></summary></entry><entry><title type="html">Ray Tracing ile Basit ve Fiziksel Tabanlı 3B Render Motoru</title><link href="https://sonsuzus.github.io/posts/ray-tracing-ile-basit-ve-fiziksel-tabanli-3b-render-motoru/" rel="alternate" type="text/html" title="Ray Tracing ile Basit ve Fiziksel Tabanlı 3B Render Motoru" /><published>2026-08-07T00:00:00+00:00</published><updated>2026-08-07T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/ray-tracing-ile-basit-ve-fiziksel-tabanli-3b-render-motoru</id><content type="html" xml:base="https://sonsuzus.github.io/posts/ray-tracing-ile-basit-ve-fiziksel-tabanli-3b-render-motoru/"><![CDATA[<p>Bir ışık ışınının kameradan çıkıp sahnedeki nesnelere çarptığını, oradan ışık kaynaklarına ve aynalara doğru sekerek yolculuğunu sürdürdüğünü hayal edin. Ray tracing, gerçek dünyadaki optik davranışları ters yönde izleyerek yansıma, aydınlatma ve gölgeleri hesaplar. Bu projede kürelerden oluşan küçük bir sahneyi render eden, gölge ışınları ve yansımalar kullanan basit bir Python motoru kuracağız.</p>

<p>``</p>

<h2 id="ray-tracing-nasıl-çalışır">Ray tracing nasıl çalışır?</h2>

<p>Gerçek dünyada fotonlar ışık kaynağından çıkar ve kameraya ulaşır. Ancak milyarlarca fotonu rastgele takip etmek verimsizdir. Klasik ray tracing bunun tersini yapar: Her piksel için kameradan sahneye bir <strong>birincil ışın</strong> gönderir. Işın bir yüzeye çarparsa en yakın kesişim noktası bulunur; ardından ışık, gölge ve yansıma hesaplanır.</p>

<p>Bir ışın parametrik olarak şöyle gösterilir:</p>

\[R(t) = O + tD\]

<p>Burada $O$ ışının başlangıç noktası, $D$ normalize edilmiş yönü, $t$ ise ışın üzerindeki mesafedir. $t &gt; 0$ koşulunu sağlayan en küçük değer, kameraya en yakın görünür yüzeyi verir.</p>

<table>
  <thead>
    <tr>
      <th>Işın türü</th>
      <th>Başlangıç</th>
      <th>Amaç</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Birincil ışın</td>
      <td>Kamera</td>
      <td>Görünen yüzeyi bulmak</td>
    </tr>
    <tr>
      <td>Gölge ışını</td>
      <td>Kesişim noktası</td>
      <td>Işığın engellenip engellenmediğini ölçmek</td>
    </tr>
    <tr>
      <td>Yansıma ışını</td>
      <td>Yüzey</td>
      <td>Aynadaki görüntüyü hesaplamak</td>
    </tr>
  </tbody>
</table>

<h2 id="küreyle-kesişim">Küreyle kesişim</h2>

<p>Merkezi $C$, yarıçapı $r$ olan kürenin denklemi $\lVert P-C\rVert^2=r^2$ biçimindedir. $P=R(t)$ yerleştirildiğinde ikinci dereceden denklem elde edilir:</p>

\[at^2+bt+c=0\]

\[a=D\cdot D,\quad b=2D\cdot(O-C),\quad c=(O-C)\cdot(O-C)-r^2\]

<p>Diskriminant $\Delta=b^2-4ac$ negatifse kesişim yoktur. Pozitifse iki çözümden en küçük pozitif olanı seçilir.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">numpy</span> <span class="k">as</span> <span class="n">np</span>

<span class="k">def</span> <span class="nf">normalize</span><span class="p">(</span><span class="n">v</span><span class="p">):</span>
    <span class="k">return</span> <span class="n">v</span> <span class="o">/</span> <span class="n">np</span><span class="p">.</span><span class="n">linalg</span><span class="p">.</span><span class="nf">norm</span><span class="p">(</span><span class="n">v</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">hit_sphere</span><span class="p">(</span><span class="n">origin</span><span class="p">,</span> <span class="n">direction</span><span class="p">,</span> <span class="n">center</span><span class="p">,</span> <span class="n">radius</span><span class="p">):</span>
    <span class="n">oc</span> <span class="o">=</span> <span class="n">origin</span> <span class="o">-</span> <span class="n">center</span>
    <span class="n">a</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">dot</span><span class="p">(</span><span class="n">direction</span><span class="p">,</span> <span class="n">direction</span><span class="p">)</span>
    <span class="n">b</span> <span class="o">=</span> <span class="mf">2.0</span> <span class="o">*</span> <span class="n">np</span><span class="p">.</span><span class="nf">dot</span><span class="p">(</span><span class="n">oc</span><span class="p">,</span> <span class="n">direction</span><span class="p">)</span>
    <span class="n">c</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">dot</span><span class="p">(</span><span class="n">oc</span><span class="p">,</span> <span class="n">oc</span><span class="p">)</span> <span class="o">-</span> <span class="n">radius</span> <span class="o">*</span> <span class="n">radius</span>
    <span class="n">delta</span> <span class="o">=</span> <span class="n">b</span> <span class="o">*</span> <span class="n">b</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">*</span> <span class="n">a</span> <span class="o">*</span> <span class="n">c</span>
    <span class="k">if</span> <span class="n">delta</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">None</span>

    <span class="n">roots</span> <span class="o">=</span> <span class="p">[(</span><span class="o">-</span><span class="n">b</span> <span class="o">-</span> <span class="n">np</span><span class="p">.</span><span class="nf">sqrt</span><span class="p">(</span><span class="n">delta</span><span class="p">))</span> <span class="o">/</span> <span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">a</span><span class="p">),</span>
             <span class="p">(</span><span class="o">-</span><span class="n">b</span> <span class="o">+</span> <span class="n">np</span><span class="p">.</span><span class="nf">sqrt</span><span class="p">(</span><span class="n">delta</span><span class="p">))</span> <span class="o">/</span> <span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">a</span><span class="p">)]</span>
    <span class="n">valid</span> <span class="o">=</span> <span class="p">[</span><span class="n">t</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">roots</span> <span class="k">if</span> <span class="n">t</span> <span class="o">&gt;</span> <span class="mf">1e-4</span><span class="p">]</span>
    <span class="k">return</span> <span class="nf">min</span><span class="p">(</span><span class="n">valid</span><span class="p">)</span> <span class="k">if</span> <span class="n">valid</span> <span class="k">else</span> <span class="bp">None</span>
</code></pre></div></div>

<p>Küçük <code class="language-plaintext highlighter-rouge">1e-4</code> eşiği, ışının çıktığı yüzeye yeniden çarpmasını önler. Bu sorun render dünyasında <strong>shadow acne</strong> olarak bilinir; görüntünüz sivilce çıkarırsa matematiği suçlayabilirsiniz.</p>

<h2 id="aydınlatma-gölge-ve-yansıma">Aydınlatma, gölge ve yansıma</h2>

<p>Mat Lambert yüzeylerde parlaklık, normal $N$ ile ışık yönü $L$ arasındaki açıya bağlıdır:</p>

\[I_d = k_d I_L \max(0,N\cdot L)\]

<p>Noktasal ışığın şiddeti ayrıca uzaklığın karesiyle azalır: $I_L=P/(4\pi d^2)$. Böylece uzaktaki nesneler fiziksel olarak daha az aydınlanır. Kesişim noktasından ışığa gönderilen gölge ışını başka bir nesneye çarparsa doğrudan aydınlatma sıfırlanır.</p>

<p>Mükemmel ayna yansımasının yönü ise şöyledir:</p>

\[R = D - 2(D\cdot N)N\]

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">reflect</span><span class="p">(</span><span class="n">direction</span><span class="p">,</span> <span class="n">normal</span><span class="p">):</span>
    <span class="k">return</span> <span class="nf">normalize</span><span class="p">(</span><span class="n">direction</span> <span class="o">-</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">np</span><span class="p">.</span><span class="nf">dot</span><span class="p">(</span><span class="n">direction</span><span class="p">,</span> <span class="n">normal</span><span class="p">)</span> <span class="o">*</span> <span class="n">normal</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">shade</span><span class="p">(</span><span class="n">point</span><span class="p">,</span> <span class="n">normal</span><span class="p">,</span> <span class="n">light_pos</span><span class="p">,</span> <span class="n">light_power</span><span class="p">,</span> <span class="n">blocked</span><span class="p">):</span>
    <span class="n">to_light</span> <span class="o">=</span> <span class="n">light_pos</span> <span class="o">-</span> <span class="n">point</span>
    <span class="n">distance</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">linalg</span><span class="p">.</span><span class="nf">norm</span><span class="p">(</span><span class="n">to_light</span><span class="p">)</span>
    <span class="n">light_dir</span> <span class="o">=</span> <span class="nf">normalize</span><span class="p">(</span><span class="n">to_light</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">blocked</span> <span class="ow">or</span> <span class="n">np</span><span class="p">.</span><span class="nf">dot</span><span class="p">(</span><span class="n">normal</span><span class="p">,</span> <span class="n">light_dir</span><span class="p">)</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">return</span> <span class="mf">0.0</span>
    <span class="k">return</span> <span class="n">light_power</span> <span class="o">*</span> <span class="n">np</span><span class="p">.</span><span class="nf">dot</span><span class="p">(</span><span class="n">normal</span><span class="p">,</span> <span class="n">light_dir</span><span class="p">)</span> <span class="o">/</span> <span class="p">(</span><span class="mi">4</span> <span class="o">*</span> <span class="n">np</span><span class="p">.</span><span class="n">pi</span> <span class="o">*</span> <span class="n">distance</span><span class="o">**</span><span class="mi">2</span><span class="p">)</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">blocked</code> değeri, gölge ışınının ışığa ulaşmadan önce nesne bulup bulmadığını belirtir. Yansıma için <code class="language-plaintext highlighter-rouge">reflect</code> yönünde yeni bir ışın gönderilir ve dönen renk yüzeyin yansıtıcılığıyla çarpılır.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th style="text-align: right">Hız etkisi</th>
      <th>Görsel katkı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Gölge ışını</td>
      <td style="text-align: right">Orta</td>
      <td>Nesneleri zemine oturtur</td>
    </tr>
    <tr>
      <td>Yansıma</td>
      <td style="text-align: right">Yüksek</td>
      <td>Ayna ve metal hissi verir</td>
    </tr>
    <tr>
      <td>Yüksek çözünürlük</td>
      <td style="text-align: right">Çok yüksek</td>
      <td>Kenar ayrıntısını artırır</td>
    </tr>
    <tr>
      <td>Çoklu örnekleme</td>
      <td style="text-align: right">Çok yüksek</td>
      <td>Tırtıklı kenarları azaltır</td>
    </tr>
  </tbody>
</table>

<p>Render döngüsünde her pikseli kamera düzlemindeki bir koordinata dönüştürün, ışını normalize edin ve <code class="language-plaintext highlighter-rouge">trace(ray, depth)</code> fonksiyonunu çağırın. Fonksiyon en yakın nesneyi bulmalı, yerel rengi hesaplamalı ve derinlik sınırı aşılmadıysa yansıma ışınını özyinelemeli izlemelidir. Üç veya dört sekme başlangıç için yeterlidir.</p>

<p>Bu temel motor; üçgen kesişimi, BVH hızlandırma yapısı, kırılma, Fresnel etkisi ve Monte Carlo örneklemesi eklenerek gerçek bir path tracer’a dönüştürülebilir. İlk görüntü yavaş üretilebilir, fakat kendi yazdığınız aynalı kürenin başka bir küreyi yansıttığını görmek beklemeye kesinlikle değer.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Proje" /><category term="ray-tracing" /><category term="3B-render" /><category term="Python" /><summary type="html"><![CDATA[Bir ışık ışınının kameradan çıkıp sahnedeki nesnelere çarptığını, oradan ışık kaynaklarına ve aynalara doğru sekerek yolculuğunu sürdürdüğünü hayal edin. Ray tracing, gerçek dünyadaki optik davranışları ters yönde izleyerek yansıma, aydınlatma ve gölgeleri hesaplar. Bu projede kürelerden oluşan küçük bir sahneyi render eden, gölge ışınları ve yansımalar kullanan basit bir Python motoru kuracağız.]]></summary></entry><entry><title type="html">Sıfırdan Mini Çekirdek: Bootloader’dan Çoklu Göreve Yolculuk</title><link href="https://sonsuzus.github.io/posts/sifirdan-mini-cekirdek-bootloaderdan-coklu-goreve-yolculuk/" rel="alternate" type="text/html" title="Sıfırdan Mini Çekirdek: Bootloader’dan Çoklu Göreve Yolculuk" /><published>2026-08-07T00:00:00+00:00</published><updated>2026-08-07T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/sifirdan-mini-cekirdek-bootloaderdan-coklu-goreve-yolculuk</id><content type="html" xml:base="https://sonsuzus.github.io/posts/sifirdan-mini-cekirdek-bootloaderdan-coklu-goreve-yolculuk/"><![CDATA[<p>Bilgisayar açıldığında bizi masaüstü, pencereler ve uygulamalar karşılamadan önce oldukça ilkel bir dünya vardır. İşlemci, bellekteki belirli bir adresten komut yürütmeye başlar; ne dosya sistemi ne süreçler ne de yardım isteyebileceğimiz bir işletim sistemi bulunur. Bu projede x86 mimarisi üzerinde küçük bir çekirdek geliştirerek bootloader, korumalı kip, kesmeler ve çoklu görev arasındaki zinciri kuracağız.</p>

<p>``</p>

<h2 id="açılış-zinciri-nasıl-çalışır">Açılış zinciri nasıl çalışır?</h2>

<p>BIOS tabanlı klasik bir sistemde ilk sektör, yani 512 baytlık boot sektörü, bellekte <code class="language-plaintext highlighter-rouge">0x7C00</code> adresine yüklenir. Son iki baytın <code class="language-plaintext highlighter-rouge">0x55AA</code> olması BIOS’a sektörün önyüklenebilir olduğunu bildirir. Bootloader’ın görevi çekirdeği diskten belleğe taşımak, uygun işlemci kipini hazırlamak ve denetimi çekirdeğin giriş noktasına bırakmaktır.</p>

<table>
  <thead>
    <tr>
      <th>Aşama</th>
      <th>İşlemci durumu</th>
      <th>Temel sorumluluk</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Boot sektörü</td>
      <td>16-bit gerçek kip</td>
      <td>Donanımı tanımak ve çekirdeği yüklemek</td>
    </tr>
    <tr>
      <td>Korumalı kipe geçiş</td>
      <td>32-bit</td>
      <td>GDT kurmak ve segmentleri ayarlamak</td>
    </tr>
    <tr>
      <td>Çekirdek başlangıcı</td>
      <td>32-bit C/Assembly</td>
      <td>Bellek, ekran ve kesmeleri hazırlamak</td>
    </tr>
    <tr>
      <td>Zamanlayıcı</td>
      <td>Kesme destekli</td>
      <td>Görevler arasında bağlam değiştirmek</td>
    </tr>
  </tbody>
</table>

<p>Boot sektörünün sonunu hazırlayan minimal NASM kodu şöyledir:</p>

<div class="language-nasm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">bits</span> <span class="mi">16</span>
<span class="nf">org</span> <span class="mh">0x7C00</span>

<span class="nf">cli</span>                 <span class="c1">; Hazırlık sırasında kesmeleri kapat</span>
<span class="nf">xor</span> <span class="nb">ax</span><span class="p">,</span> <span class="nb">ax</span>
<span class="nf">mov</span> <span class="nb">ds</span><span class="p">,</span> <span class="nb">ax</span>
<span class="nf">mov</span> <span class="nb">ss</span><span class="p">,</span> <span class="nb">ax</span>
<span class="nf">mov</span> <span class="nb">sp</span><span class="p">,</span> <span class="mh">0x7C00</span>      <span class="c1">; Geçici yığın oluştur</span>

<span class="nl">hang:</span>
    <span class="nf">hlt</span>
    <span class="nf">jmp</span> <span class="nv">hang</span>

<span class="kd">times</span> <span class="mi">510</span><span class="o">-</span><span class="p">(</span><span class="kc">$</span><span class="o">-</span><span class="kc">$$</span><span class="p">)</span> <span class="nv">db</span> <span class="mi">0</span>
<span class="kd">dw</span> <span class="mh">0xAA55</span>
</code></pre></div></div>

<p>Buradaki <code class="language-plaintext highlighter-rouge">$</code> mevcut adresi, <code class="language-plaintext highlighter-rouge">$$</code> ise bölümün başlangıcını gösterir. Dolgu miktarı matematiksel olarak $510-(\text{mevcut konum}-\text{başlangıç})$ biçiminde hesaplanır.</p>

<h2 id="korumalı-kip-ve-çekirdeğe-geçiş">Korumalı kip ve çekirdeğe geçiş</h2>

<p>32-bit korumalı kip için önce Global Descriptor Table oluşturulur. GDT, kod ve veri segmentlerinin taban adresi, sınırı ve erişim haklarını tanımlar. Ardından <code class="language-plaintext highlighter-rouge">CR0</code> yazmacındaki PE biti etkinleştirilir:</p>

<div class="language-nasm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">cli</span>
<span class="nf">lgdt</span> <span class="p">[</span><span class="nv">gdt_descriptor</span><span class="p">]</span>
<span class="nf">mov</span> <span class="nb">eax</span><span class="p">,</span> <span class="nb">cr0</span>
<span class="nf">or</span> <span class="nb">eax</span><span class="p">,</span> <span class="mi">1</span>
<span class="nf">mov</span> <span class="nb">cr0</span><span class="p">,</span> <span class="nb">eax</span>
<span class="nf">jmp</span> <span class="mh">0x08</span><span class="p">:</span><span class="nv">protected_mode</span>
</code></pre></div></div>

<p>Uzak atlama, işlemcinin komut kuyruğunu temizler ve yeni kod segmentini yükler. Çekirdeği C ile yazmak geliştirmeyi kolaylaştırır; ancak standart kütüphane kullanılamaz. Bu nedenle <code class="language-plaintext highlighter-rouge">memcpy</code>, <code class="language-plaintext highlighter-rouge">memset</code> ve ekran çıktısı gibi araçları kendimiz üretiriz.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">volatile</span> <span class="kt">unsigned</span> <span class="kt">short</span> <span class="o">*</span><span class="n">vga</span> <span class="o">=</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">short</span> <span class="o">*</span><span class="p">)</span><span class="mh">0xB8000</span><span class="p">;</span>

<span class="kt">void</span> <span class="nf">put_char</span><span class="p">(</span><span class="kt">char</span> <span class="n">c</span><span class="p">,</span> <span class="kt">int</span> <span class="n">position</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">vga</span><span class="p">[</span><span class="n">position</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="mh">0x0F</span> <span class="o">&lt;&lt;</span> <span class="mi">8</span><span class="p">)</span> <span class="o">|</span> <span class="n">c</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">kernel_main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">put_char</span><span class="p">(</span><span class="sc">'K'</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="cm">/* VGA metin belleğine doğrudan yazar */</span>
    <span class="k">for</span> <span class="p">(;;)</span> <span class="n">__asm__</span> <span class="k">volatile</span><span class="p">(</span><span class="s">"hlt"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="kesme-olmadan-çoklu-görev-olmaz">Kesme olmadan çoklu görev olmaz</h2>

<p>Çekirdeğin düzenli aralıklarla kontrolü geri alması için PIT zamanlayıcısı ve Interrupt Descriptor Table gerekir. PIT frekansı yaklaşık $1{,}193{,}182$ Hz’dir. İstenen kesme frekansı $f$ ise gönderilecek bölen</p>

\[d=\frac{1{,}193{,}182}{f}\]

<p>olarak hesaplanır. Örneğin 100 Hz için yaklaşık <code class="language-plaintext highlighter-rouge">11931</code> kullanılır. Her zamanlayıcı kesmesinde çalışan görevin yazmaçları saklanır ve sıradaki görevin bağlamı yüklenir.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">typedef</span> <span class="k">struct</span> <span class="p">{</span>
    <span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">esp</span><span class="p">;</span>
    <span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">id</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">active</span><span class="p">;</span>
<span class="p">}</span> <span class="n">task_t</span><span class="p">;</span>

<span class="kt">int</span> <span class="n">current</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">task_t</span> <span class="n">tasks</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>

<span class="kt">void</span> <span class="nf">schedule</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">current</span> <span class="o">=</span> <span class="p">(</span><span class="n">current</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="mi">2</span><span class="p">;</span>
    <span class="n">switch_stack</span><span class="p">(</span><span class="n">tasks</span><span class="p">[</span><span class="n">current</span><span class="p">].</span><span class="n">esp</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu basit yöntem round-robin zamanlamadır. Her görev eşit zaman dilimi alır; $n$ görev ve $T$ uzunluğunda dilim için aynı göreve yaklaşık $nT$ sonra dönülür. Gerçek bir bağlam değişiminde <code class="language-plaintext highlighter-rouge">ESP</code> dışında genel yazmaçlar, bayraklar ve gerekirse adres uzayı da korunmalıdır.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Avantaj</th>
      <th>Dezavantaj</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>İşbirlikçi görev</td>
      <td>Basit ve öngörülebilir</td>
      <td>Görev kontrolü bırakmazsa sistem donar</td>
    </tr>
    <tr>
      <td>Kesintili görev</td>
      <td>Daha adil ve dayanıklı</td>
      <td>Kesme ve bağlam yönetimi karmaşıktır</td>
    </tr>
    <tr>
      <td>Ayrı adres uzayı</td>
      <td>Güçlü süreç yalıtımı</td>
      <td>Sayfalama ve TLB maliyeti getirir</td>
    </tr>
  </tbody>
</table>

<p>Projeyi QEMU üzerinde çalıştırmak, fiziksel donanımı yanlışlıkla kilitlemeden seri port günlüklerini ve işlemci durumunu incelemeyi sağlar. İlk hedefiniz ekrana iki görevin dönüşümlü karakter yazması olabilir. Bu küçük başarı, modern işletim sistemlerinin arkasındaki görünmez orkestrayı elle kurduğunuz anlamına gelir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Proje" /><category term="işletim sistemi" /><category term="kernel geliştirme" /><category term="multitasking" /><summary type="html"><![CDATA[Bilgisayar açıldığında bizi masaüstü, pencereler ve uygulamalar karşılamadan önce oldukça ilkel bir dünya vardır. İşlemci, bellekteki belirli bir adresten komut yürütmeye başlar; ne dosya sistemi ne süreçler ne de yardım isteyebileceğimiz bir işletim sistemi bulunur. Bu projede x86 mimarisi üzerinde küçük bir çekirdek geliştirerek bootloader, korumalı kip, kesmeler ve çoklu görev arasındaki zinciri kuracağız.]]></summary></entry><entry><title type="html">Sıfırdan Turing Tam Bir Programlama Dili Tasarlamak</title><link href="https://sonsuzus.github.io/posts/sifirdan-turing-tam-bir-programlama-dili-tasarlamak/" rel="alternate" type="text/html" title="Sıfırdan Turing Tam Bir Programlama Dili Tasarlamak" /><published>2026-08-07T00:00:00+00:00</published><updated>2026-08-07T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/sifirdan-turing-tam-bir-programlama-dili-tasarlamak</id><content type="html" xml:base="https://sonsuzus.github.io/posts/sifirdan-turing-tam-bir-programlama-dili-tasarlamak/"><![CDATA[<p>Bir programlama dili yapmak, bilgisayara yeni kelimeler öğretmekten çok daha fazlasıdır: Önce metni parçalara ayırır, sonra bu parçaların dilbilgisine uyup uymadığını denetler ve en sonunda anlamlarını çalıştırırsınız. Bu projede değişkenleri, aritmetik işlemleri, koşulları ve döngüleri destekleyen MiniLang adında küçük ama teorik olarak Turing tam bir dil tasarlayacağız.
``</p>

<h2 id="turing-tamlık-ne-anlama-gelir">Turing tamlık ne anlama gelir?</h2>

<p>Bir dil, yeterli zaman ve bellek verildiğinde herhangi bir hesaplanabilir algoritmayı ifade edebiliyorsa Turing tam kabul edilir. Pratik bir dil için temel gereksinimler şunlardır:</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>MiniLang karşılığı</th>
      <th>Neden gerekli?</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Bellek</td>
      <td>Değişkenler</td>
      <td>Ara sonuçları saklamak</td>
    </tr>
    <tr>
      <td>Hesaplama</td>
      <td><code class="language-plaintext highlighter-rouge">+</code>, <code class="language-plaintext highlighter-rouge">-</code>, <code class="language-plaintext highlighter-rouge">*</code>, <code class="language-plaintext highlighter-rouge">/</code></td>
      <td>Veriyi dönüştürmek</td>
    </tr>
    <tr>
      <td>Karar</td>
      <td><code class="language-plaintext highlighter-rouge">if</code></td>
      <td>Farklı yürütme yolları oluşturmak</td>
    </tr>
    <tr>
      <td>Tekrar</td>
      <td><code class="language-plaintext highlighter-rouge">while</code></td>
      <td>Sınırsız adım gerçekleştirmek</td>
    </tr>
  </tbody>
</table>

<p>Özellikle <code class="language-plaintext highlighter-rouge">while</code> döngüsü ve teorik olarak sınırsız büyüyebilen sayılar sayesinde dilimiz, bir sayaç makinesini simüle edebilir. Örneğin bir sayıyı tekrar tekrar azaltmak şu geçişi oluşturur:</p>

\[x_{n+1}=x_n-1\]

<p>Koşullu sıçramalarla birleşen bu işlem, genel hesaplama modellerini ifade etmek için yeterlidir. Gerçek bilgisayarların belleği elbette sonludur; Turing tamlık idealize edilmiş sınırsız kaynak varsayımına dayanır.</p>

<h2 id="dilin-söz-dizimi">Dilin söz dizimi</h2>

<p>MiniLang ile faktöriyel hesabı şöyle görünebilir:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>let n = 5;
let result = 1;
while (n &gt; 1) {
    result = result * n;
    n = n - 1;
}
print result;
</code></pre></div></div>

<p>Burada amaçlanan sonuç $5! = 5\times4\times3\times2\times1 = 120$ değeridir. Şimdi kaynak kodun yorumlayıcıdan geçerken uğradığı üç durağa bakalım.</p>

<h2 id="1-lexer-metni-jetonlara-ayırmak">1. Lexer: Metni jetonlara ayırmak</h2>

<p>Lexer, karakterleri <code class="language-plaintext highlighter-rouge">NUMBER</code>, <code class="language-plaintext highlighter-rouge">IDENT</code>, <code class="language-plaintext highlighter-rouge">PLUS</code> gibi tokenlara dönüştürür. Böylece parser tek tek karakterlerle boğuşmaz.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">re</span>

<span class="n">TOKEN_RE</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="nf">compile</span><span class="p">(</span>
    <span class="sa">r</span><span class="sh">'</span><span class="s">(?P&lt;NUMBER&gt;\d+)|(?P&lt;IDENT&gt;[A-Za-z_]\w*)|</span><span class="sh">'</span>
    <span class="sa">r</span><span class="sh">'</span><span class="s">(?P&lt;OP&gt;==|&gt;|[+\-*/=;(){}])|(?P&lt;SPACE&gt;\s+)</span><span class="sh">'</span>
<span class="p">)</span>

<span class="k">def</span> <span class="nf">lex</span><span class="p">(</span><span class="n">source</span><span class="p">):</span>
    <span class="n">tokens</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">TOKEN_RE</span><span class="p">.</span><span class="nf">finditer</span><span class="p">(</span><span class="n">source</span><span class="p">):</span>
        <span class="n">kind</span><span class="p">,</span> <span class="n">value</span> <span class="o">=</span> <span class="k">match</span><span class="p">.</span><span class="n">lastgroup</span><span class="p">,</span> <span class="k">match</span><span class="p">.</span><span class="nf">group</span><span class="p">()</span>
        <span class="k">if</span> <span class="n">kind</span> <span class="o">!=</span> <span class="sh">'</span><span class="s">SPACE</span><span class="sh">'</span><span class="p">:</span>
            <span class="n">tokens</span><span class="p">.</span><span class="nf">append</span><span class="p">((</span><span class="n">kind</span><span class="p">,</span> <span class="n">value</span><span class="p">))</span>
    <span class="k">return</span> <span class="n">tokens</span>
</code></pre></div></div>

<p>Bu fonksiyon boşlukları atlar, sayıları ve isimleri tanır. Sağlam bir sürüm ayrıca eşleşmeyen karakterlerin konumunu bildirerek anlaşılır hata mesajları üretmelidir.</p>

<h2 id="2-parser-tokenlardan-anlamlı-bir-ağaç-kurmak">2. Parser: Tokenlardan anlamlı bir ağaç kurmak</h2>

<p>Parser, token dizisini soyut sözdizimi ağacına, yani AST’ye çevirir. Basit gramerimizin özeti şöyledir:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>statement  -&gt; 'let' IDENT '=' expression ';'
            | IDENT '=' expression ';'
            | 'while' '(' expression ')' block
            | 'print' expression ';'
expression -&gt; comparison
comparison -&gt; term ('&gt;' term)*
term       -&gt; factor (('+' | '-') factor)*
factor     -&gt; primary (('*' | '/') primary)*
</code></pre></div></div>

<p>Öncelik katmanları önemlidir: <code class="language-plaintext highlighter-rouge">2 + 3 * 4</code>, $(2+3)\times4$ değil, $2+(3\times4)=14$ biçiminde ayrıştırılmalıdır. Recursive descent yaklaşımında her gramer kuralı bir Python fonksiyonuna dönüştürülür. Örneğin toplama katmanı:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">parse_term</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
    <span class="n">node</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="nf">parse_factor</span><span class="p">()</span>
    <span class="k">while</span> <span class="n">self</span><span class="p">.</span><span class="nf">peek_value</span><span class="p">()</span> <span class="ow">in</span> <span class="p">(</span><span class="sh">'</span><span class="s">+</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">-</span><span class="sh">'</span><span class="p">):</span>
        <span class="n">operator</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="nf">advance</span><span class="p">()[</span><span class="mi">1</span><span class="p">]</span>
        <span class="n">right</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="nf">parse_factor</span><span class="p">()</span>
        <span class="n">node</span> <span class="o">=</span> <span class="p">(</span><span class="sh">'</span><span class="s">binary</span><span class="sh">'</span><span class="p">,</span> <span class="n">operator</span><span class="p">,</span> <span class="n">node</span><span class="p">,</span> <span class="n">right</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">node</span>
</code></pre></div></div>

<p>Üretilen tuple, operatörü ve iki alt ifadeyi taşıyan küçük bir AST düğümüdür.</p>

<h2 id="3-yorumlayıcı-ağacı-çalıştırmak">3. Yorumlayıcı: Ağacı çalıştırmak</h2>

<p>Yorumlayıcı değişkenleri bir sözlükte tutar ve AST düğümlerini değerlendirir:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">evaluate</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">env</span><span class="p">):</span>
    <span class="n">kind</span> <span class="o">=</span> <span class="n">node</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
    <span class="k">if</span> <span class="n">kind</span> <span class="o">==</span> <span class="sh">'</span><span class="s">number</span><span class="sh">'</span><span class="p">:</span>
        <span class="k">return</span> <span class="nf">int</span><span class="p">(</span><span class="n">node</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
    <span class="k">if</span> <span class="n">kind</span> <span class="o">==</span> <span class="sh">'</span><span class="s">variable</span><span class="sh">'</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">env</span><span class="p">[</span><span class="n">node</span><span class="p">[</span><span class="mi">1</span><span class="p">]]</span>
    <span class="k">if</span> <span class="n">kind</span> <span class="o">==</span> <span class="sh">'</span><span class="s">binary</span><span class="sh">'</span><span class="p">:</span>
        <span class="n">_</span><span class="p">,</span> <span class="n">op</span><span class="p">,</span> <span class="n">left</span><span class="p">,</span> <span class="n">right</span> <span class="o">=</span> <span class="n">node</span>
        <span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="nf">evaluate</span><span class="p">(</span><span class="n">left</span><span class="p">,</span> <span class="n">env</span><span class="p">),</span> <span class="nf">evaluate</span><span class="p">(</span><span class="n">right</span><span class="p">,</span> <span class="n">env</span><span class="p">)</span>
        <span class="n">operations</span> <span class="o">=</span> <span class="p">{</span>
            <span class="sh">'</span><span class="s">+</span><span class="sh">'</span><span class="p">:</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">,</span> <span class="sh">'</span><span class="s">-</span><span class="sh">'</span><span class="p">:</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">a</span> <span class="o">-</span> <span class="n">b</span><span class="p">,</span>
            <span class="sh">'</span><span class="s">*</span><span class="sh">'</span><span class="p">:</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">a</span> <span class="o">*</span> <span class="n">b</span><span class="p">,</span> <span class="sh">'</span><span class="s">/</span><span class="sh">'</span><span class="p">:</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">a</span> <span class="o">//</span> <span class="n">b</span><span class="p">,</span>
            <span class="sh">'</span><span class="s">&gt;</span><span class="sh">'</span><span class="p">:</span> <span class="k">lambda</span><span class="p">:</span> <span class="nf">int</span><span class="p">(</span><span class="n">a</span> <span class="o">&gt;</span> <span class="n">b</span><span class="p">)</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">operations</span><span class="p">[</span><span class="n">op</span><span class="p">]()</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">while</code> düğümü için koşul sıfır olmadığı sürece gövde tekrar yorumlanır. Atama düğümü de <code class="language-plaintext highlighter-rouge">env[name] = evaluate(expression, env)</code> işlemini yapar. Böylece lexer harfleri tokenlara, parser tokenları ağaca, yorumlayıcı ise ağacı davranışa dönüştürür. Birkaç hata mesajı, fonksiyon desteği ve REPL eklediğinizde MiniLang artık oyuncak görünümündeki ciddi bir hesaplama laboratuvarıdır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Proje" /><category term="programlama dili" /><category term="lexer-parser" /><category term="yorumlayıcı" /><summary type="html"><![CDATA[Bir programlama dili yapmak, bilgisayara yeni kelimeler öğretmekten çok daha fazlasıdır: Önce metni parçalara ayırır, sonra bu parçaların dilbilgisine uyup uymadığını denetler ve en sonunda anlamlarını çalıştırırsınız. Bu projede değişkenleri, aritmetik işlemleri, koşulları ve döngüleri destekleyen MiniLang adında küçük ama teorik olarak Turing tam bir dil tasarlayacağız.]]></summary></entry><entry><title type="html">Sürü Zekâsı Simülasyonu: Boids ile Kuş ve Balık Sürüleri</title><link href="https://sonsuzus.github.io/posts/suru-zekasi-simulasyonu-boids-ile-kus-ve-balik-suruleri/" rel="alternate" type="text/html" title="Sürü Zekâsı Simülasyonu: Boids ile Kuş ve Balık Sürüleri" /><published>2026-08-07T00:00:00+00:00</published><updated>2026-08-07T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/suru-zekasi-simulasyonu-boids-ile-kus-ve-balik-suruleri</id><content type="html" xml:base="https://sonsuzus.github.io/posts/suru-zekasi-simulasyonu-boids-ile-kus-ve-balik-suruleri/"><![CDATA[<p>Gökyüzünde aynı anda yön değiştiren kuşlar veya suda tek bir canlıymış gibi ilerleyen balıklar merkezi bir komut sistemine sahip değildir. Buna rağmen ortaya son derece düzenli ve karmaşık hareketler çıkar. Sürü zekâsı simülasyonu, her bireye birkaç basit kural vererek bu şaşırtıcı davranışları bilgisayar ortamında yeniden üretmemizi sağlar.
``</p>

<h2 id="sürü-zekâsı-nedir">Sürü zekâsı nedir?</h2>

<p>Sürü zekâsı, merkezi yönetim olmadan çalışan çok sayıda basit ajanın yerel etkileşimlerinden doğan kolektif davranıştır. Bir kuş, bütün sürünün konumunu hesaplamaz; yalnızca yakınındaki komşularını gözlemler. Bu yaklaşım robot koordinasyonu, trafik modelleme, oyun yapay zekâsı ve optimizasyon gibi alanlarda kullanılır.</p>

<p>Craig Reynolds tarafından geliştirilen <strong>Boids</strong> modeli, her kuşu bağımsız bir ajan olarak ele alır. Ajanın konumu $p_i$, hızı ise $v_i$ olsun. Her simülasyon adımında hareket yaklaşık olarak şöyle güncellenir:</p>

\[v_i(t+1) = v_i(t) + w_s S_i + w_a A_i + w_c C_i\]

\[p_i(t+1) = p_i(t) + v_i(t+1)\]

<p>Buradaki $S_i$ ayrılma, $A_i$ hizalanma ve $C_i$ bütünleşme kuvvetidir. $w_s$, $w_a$ ve $w_c$ katsayıları davranışların etkisini belirler.</p>

<table>
  <thead>
    <tr>
      <th>Kural</th>
      <th>Ajanın yaptığı</th>
      <th>Ortaya çıkan etki</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Ayrılma</td>
      <td>Çok yakın komşulardan uzaklaşır</td>
      <td>Çarpışmalar azalır</td>
    </tr>
    <tr>
      <td>Hizalanma</td>
      <td>Komşuların ortalama yönüne döner</td>
      <td>Sürü ortak yönde ilerler</td>
    </tr>
    <tr>
      <td>Bütünleşme</td>
      <td>Komşuların merkezine yaklaşır</td>
      <td>Grup dağılmaz</td>
    </tr>
  </tbody>
</table>

<p>Bu kuralların hiçbiri tek başına gerçekçi bir sürü oluşturmaz. Ayrılma fazla güçlü olursa ajanlar birbirinden kaçar; bütünleşme baskın olursa ekranın ortasında sıkışmış bir top oluşur. Eğlence, katsayılarla oynayıp düzen ile kaos arasındaki dengeyi bulmaktadır.</p>

<h2 id="python-ile-hareket-çekirdeği">Python ile hareket çekirdeği</h2>

<p>Aşağıdaki sınıf, bir ajanın komşularına bakarak üç temel kuvveti hesaplar. NumPy vektör işlemlerini kolaylaştırır:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">numpy</span> <span class="k">as</span> <span class="n">np</span>

<span class="k">class</span> <span class="nc">Boid</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">position</span><span class="p">,</span> <span class="n">velocity</span><span class="p">):</span>
        <span class="n">self</span><span class="p">.</span><span class="n">position</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">array</span><span class="p">(</span><span class="n">position</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="nb">float</span><span class="p">)</span>
        <span class="n">self</span><span class="p">.</span><span class="n">velocity</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">array</span><span class="p">(</span><span class="n">velocity</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="nb">float</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">update</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">flock</span><span class="p">,</span> <span class="n">radius</span><span class="o">=</span><span class="mi">60</span><span class="p">):</span>
        <span class="n">neighbors</span> <span class="o">=</span> <span class="p">[</span><span class="n">b</span> <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">flock</span>
                     <span class="k">if</span> <span class="n">b</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">self</span> <span class="ow">and</span>
                     <span class="n">np</span><span class="p">.</span><span class="n">linalg</span><span class="p">.</span><span class="nf">norm</span><span class="p">(</span><span class="n">b</span><span class="p">.</span><span class="n">position</span> <span class="o">-</span> <span class="n">self</span><span class="p">.</span><span class="n">position</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">radius</span><span class="p">]</span>

        <span class="k">if</span> <span class="ow">not</span> <span class="n">neighbors</span><span class="p">:</span>
            <span class="n">self</span><span class="p">.</span><span class="n">position</span> <span class="o">+=</span> <span class="n">self</span><span class="p">.</span><span class="n">velocity</span>
            <span class="k">return</span>

        <span class="n">center</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">mean</span><span class="p">([</span><span class="n">b</span><span class="p">.</span><span class="n">position</span> <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">neighbors</span><span class="p">],</span> <span class="n">axis</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
        <span class="n">average_velocity</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">mean</span><span class="p">([</span><span class="n">b</span><span class="p">.</span><span class="n">velocity</span> <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">neighbors</span><span class="p">],</span> <span class="n">axis</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>

        <span class="n">cohesion</span> <span class="o">=</span> <span class="p">(</span><span class="n">center</span> <span class="o">-</span> <span class="n">self</span><span class="p">.</span><span class="n">position</span><span class="p">)</span> <span class="o">*</span> <span class="mf">0.002</span>
        <span class="n">alignment</span> <span class="o">=</span> <span class="p">(</span><span class="n">average_velocity</span> <span class="o">-</span> <span class="n">self</span><span class="p">.</span><span class="n">velocity</span><span class="p">)</span> <span class="o">*</span> <span class="mf">0.05</span>
        <span class="n">separation</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">zeros</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>

        <span class="k">for</span> <span class="n">other</span> <span class="ow">in</span> <span class="n">neighbors</span><span class="p">:</span>
            <span class="n">difference</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="n">position</span> <span class="o">-</span> <span class="n">other</span><span class="p">.</span><span class="n">position</span>
            <span class="n">distance</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">linalg</span><span class="p">.</span><span class="nf">norm</span><span class="p">(</span><span class="n">difference</span><span class="p">)</span>
            <span class="k">if</span> <span class="mi">0</span> <span class="o">&lt;</span> <span class="n">distance</span> <span class="o">&lt;</span> <span class="mi">20</span><span class="p">:</span>
                <span class="n">separation</span> <span class="o">+=</span> <span class="n">difference</span> <span class="o">/</span> <span class="n">distance</span>

        <span class="n">self</span><span class="p">.</span><span class="n">velocity</span> <span class="o">+=</span> <span class="n">cohesion</span> <span class="o">+</span> <span class="n">alignment</span> <span class="o">+</span> <span class="n">separation</span> <span class="o">*</span> <span class="mf">0.08</span>

        <span class="n">speed</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">linalg</span><span class="p">.</span><span class="nf">norm</span><span class="p">(</span><span class="n">self</span><span class="p">.</span><span class="n">velocity</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">speed</span> <span class="o">&gt;</span> <span class="mi">4</span><span class="p">:</span>
            <span class="n">self</span><span class="p">.</span><span class="n">velocity</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="n">velocity</span> <span class="o">/</span> <span class="n">speed</span> <span class="o">*</span> <span class="mi">4</span>

        <span class="n">self</span><span class="p">.</span><span class="n">position</span> <span class="o">+=</span> <span class="n">self</span><span class="p">.</span><span class="n">velocity</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">neighbors</code> listesi algı yarıçapındaki ajanları seçer. Bütünleşme komşuların geometrik merkezini, hizalanma ortalama hızını hedefler. Ayrılma ise mesafe azaldıkça ajanı ters yönde iter. Hız sınırı koymak önemlidir; aksi hâlde kuvvetler birikerek kuşları roket hızına ulaştırabilir.</p>

<h2 id="simülasyonu-canlandırmak">Simülasyonu canlandırmak</h2>

<p>Pygame, ajanları ekranda göstermek için kullanılabilir. Her karede tüm ajanlar güncellenir, ekran sınırını aşanlar karşı taraftan çıkarılır ve küçük daireler çizilir:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="n">boid</span> <span class="ow">in</span> <span class="n">flock</span><span class="p">:</span>
    <span class="n">boid</span><span class="p">.</span><span class="nf">update</span><span class="p">(</span><span class="n">flock</span><span class="p">)</span>
    <span class="n">boid</span><span class="p">.</span><span class="n">position</span> <span class="o">%=</span> <span class="p">[</span><span class="n">width</span><span class="p">,</span> <span class="n">height</span><span class="p">]</span>
    <span class="n">pygame</span><span class="p">.</span><span class="n">draw</span><span class="p">.</span><span class="nf">circle</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span> <span class="p">(</span><span class="mi">80</span><span class="p">,</span> <span class="mi">210</span><span class="p">,</span> <span class="mi">255</span><span class="p">),</span>
                       <span class="n">boid</span><span class="p">.</span><span class="n">position</span><span class="p">.</span><span class="nf">astype</span><span class="p">(</span><span class="nb">int</span><span class="p">),</span> <span class="mi">4</span><span class="p">)</span>
</code></pre></div></div>

<p>Kuş görünümü için hız yönünde dönen üçgenler, balık görünümü için kuyruk animasyonu eklenebilir. Fare imlecini bir avcı olarak tanımlayıp yakındaki ajanlara kaçış kuvveti uygulamak da sürünün aniden yarılması gibi etkileyici davranışlar üretir.</p>

<h2 id="deney-fikirleri">Deney fikirleri</h2>

<p>Ajan sayısını, algı yarıçapını ve kural ağırlıklarını çalışma sırasında değiştirin. Sonuçları yalnızca görsel olarak değil, ortalama komşu mesafesi ve yön uyumu gibi ölçülerle de inceleyin. Örneğin yön uyumu, normalize edilmiş hızların ortalamasıyla $0$ ile $1$ arasında ölçülebilir. Basit yerel kararların küresel düzeyde nasıl örgütlendiğini görmek, bu projeyi hem öğretici hem de hipnotik derecede eğlenceli yapar.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Proje" /><category term="sürü zekâsı" /><category term="boids" /><category term="simülasyon" /><summary type="html"><![CDATA[Gökyüzünde aynı anda yön değiştiren kuşlar veya suda tek bir canlıymış gibi ilerleyen balıklar merkezi bir komut sistemine sahip değildir. Buna rağmen ortaya son derece düzenli ve karmaşık hareketler çıkar. Sürü zekâsı simülasyonu, her bireye birkaç basit kural vererek bu şaşırtıcı davranışları bilgisayar ortamında yeniden üretmemizi sağlar.]]></summary></entry><entry><title type="html">Turing’den Transformer’lara: Yapay Zekânın Tarihsel ve Teorik Yolculuğu</title><link href="https://sonsuzus.github.io/posts/turingden-transformerlara-yapay-zekanin-tarihsel-ve-teorik-yolculugu/" rel="alternate" type="text/html" title="Turing’den Transformer’lara: Yapay Zekânın Tarihsel ve Teorik Yolculuğu" /><published>2026-08-07T00:00:00+00:00</published><updated>2026-08-07T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/turingden-transformerlara-yapay-zekanin-tarihsel-ve-teorik-yolculugu</id><content type="html" xml:base="https://sonsuzus.github.io/posts/turingden-transformerlara-yapay-zekanin-tarihsel-ve-teorik-yolculugu/"><![CDATA[<p>Yapay zekâ, makinelerin yalnızca hesap yapmasını değil; algılama, öğrenme, akıl yürütme ve karar verme gibi zekâyla ilişkilendirilen görevleri gerçekleştirmesini amaçlayan disiplinler arası bir alandır. Bugün sohbet botlarından otonom araçlara kadar her yerde karşımıza çıksa da bu yolculuk, “Makineler düşünebilir mi?” sorusuyla başladı.
``</p>
<h2 id="turing-testi-ve-zekânın-ölçülmesi">Turing Testi ve zekânın ölçülmesi</h2>

<p>Alan Turing, 1950 tarihli <em>Computing Machinery and Intelligence</em> makalesinde düşünmenin kesin bir tanımını yapmak yerine davranışsal bir ölçüt önerdi. <strong>Taklit Oyunu</strong> olarak adlandırılan ve sonradan Turing Testi diye bilinen düzende bir insan değerlendirici, yazılı mesajlarla insan ve makineyle konuşur. Değerlendirici hangisinin makine olduğunu güvenilir biçimde ayırt edemiyorsa makine, insan benzeri dil davranışı sergilemiş kabul edilir.</p>

<p>Test önemli bir felsefi dönüşüm yarattı: İç dünyası gözlemlenemeyen bir sistemin zekâsı, davranışı üzerinden değerlendirilebilirdi. Ancak test; bilinç, doğruluk veya gerçek anlama garantisi vermez. Son derece ikna edici biçimde yanlış konuşan bir program testi geçebilir. Günümüzün büyük dil modelleri etrafındaki tartışmalar da tam olarak bu noktaya dokunur.</p>

<h2 id="sembolik-yapay-zekâ-dönemi">Sembolik yapay zekâ dönemi</h2>

<p>“Yapay zekâ” terimi, 1956 Dartmouth çalıştayında akademik kimlik kazandı. İlk araştırmacılar zekânın semboller ve açık kurallar aracılığıyla modellenebileceğine inanıyordu. Bu yaklaşımda bilgi, mantıksal ifadeler şeklinde temsil edilir:</p>

\[İnsan(x) \land İnsanlarınÖlümlüOlması \Rightarrow Ölümlü(x)\]

<p>Bir uzman sistem, mevcut olgulara kurallar uygulayarak yeni sonuçlar üretir. Örneğin basit bir teşhis mekanizması şöyle yazılabilir:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">belirtiler</span> <span class="o">=</span> <span class="p">{</span><span class="sh">"</span><span class="s">ates</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">oksuruk</span><span class="sh">"</span><span class="p">}</span>

<span class="k">if</span> <span class="p">{</span><span class="sh">"</span><span class="s">ates</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">oksuruk</span><span class="sh">"</span><span class="p">}.</span><span class="nf">issubset</span><span class="p">(</span><span class="n">belirtiler</span><span class="p">):</span>
    <span class="n">sonuc</span> <span class="o">=</span> <span class="sh">"</span><span class="s">Solunum yolu enfeksiyonu araştırılmalı</span><span class="sh">"</span>
<span class="k">else</span><span class="p">:</span>
    <span class="n">sonuc</span> <span class="o">=</span> <span class="sh">"</span><span class="s">Yeterli kural eşleşmesi yok</span><span class="sh">"</span>

<span class="nf">print</span><span class="p">(</span><span class="n">sonuc</span><span class="p">)</span>
</code></pre></div></div>

<p>Bu kod, sembolik yaklaşımın şeffaflığını gösterir: Sonucun hangi koşuldan çıktığı bellidir. Fakat gerçek dünya istisnalarla doludur. Binlerce kuralı elle yazmak, çelişkileri çözmek ve belirsizliği temsil etmek zorlaşır. Bu darboğazlar ile sınırlı donanım, 1970’ler ve 1980’lerin sonlarında “yapay zekâ kışı” denilen yatırım ve ilgi düşüşlerine katkıda bulundu.</p>

<h2 id="veriden-öğrenmeye-geçiş">Veriden öğrenmeye geçiş</h2>

<p>Modern istatistiksel yaklaşımda geliştirici bütün kuralları yazmaz; model, örneklerden örüntü öğrenir. Amaç çoğu zaman belirli girdiler altında en olası çıktıyı bulmaktır:</p>

\[\hat{y}=\arg\max_y P(y\mid x)\]

<p>Bu dönüşümü daha fazla dijital veri, güçlü işlemciler, internet ve gelişmiş optimizasyon yöntemleri hızlandırdı. 1990’larda olasılıksal modeller ve destek vektör makineleri öne çıkarken, 2010’larda derin öğrenme görüntü ve konuşma alanlarında büyük sıçramalar sağladı. 2012’de AlexNet’in başarısı, GPU destekli sinir ağlarının gücünü görünür hâle getirdi.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Sembolik yaklaşım</th>
      <th>İstatistiksel yaklaşım</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Bilgi kaynağı</td>
      <td>İnsan tarafından yazılan kurallar</td>
      <td>Veriden öğrenilen parametreler</td>
    </tr>
    <tr>
      <td>Güçlü yanı</td>
      <td>Açıklanabilir akıl yürütme</td>
      <td>Gürültüye ve karmaşık örüntülere uyum</td>
    </tr>
    <tr>
      <td>Zayıf yanı</td>
      <td>Kural patlaması ve kırılganlık</td>
      <td>Veri ihtiyacı ve düşük açıklanabilirlik</td>
    </tr>
    <tr>
      <td>Tipik örnek</td>
      <td>Uzman sistem</td>
      <td>Sinir ağı</td>
    </tr>
  </tbody>
</table>

<h2 id="transformer-çağı-ve-üretken-yapay-zekâ">Transformer çağı ve üretken yapay zekâ</h2>

<p>2017’de tanıtılan Transformer mimarisi, dizilerdeki öğelerin birbirleriyle ilişkisini <strong>dikkat mekanizması</strong> üzerinden hesapladı. Basitleştirilmiş dikkat formülü şöyledir:</p>

\[Attention(Q,K,V)=softmax(QK^T/\sqrt{d_k})V\]

<p>Bu yapı paralel eğitime elverişli olduğu için devasa metin koleksiyonlarından dil örüntülerinin öğrenilmesini kolaylaştırdı. Büyük dil modelleri bir sonraki belirtecin olasılığını tahmin ederek eğitilse de ölçek büyüdükçe özetleme, kod üretme ve soru yanıtlama gibi yetenekler sergiledi.</p>

<p>Yine de günümüz yapay zekâsı kusursuz değildir: Yanlış bilgi üretebilir, eğitim verilerindeki önyargıları yansıtabilir ve yüksek enerji tüketebilir. Alanın geleceği muhtemelen sembolik yöntemlerle istatistiksel öğrenmenin rakip değil, tamamlayıcı kabul edildiği hibrit sistemlerde yatıyor. Kısacası Turing’in sorusu hâlâ masada; yalnızca makinelerin verdiği cevaplar artık çok daha etkileyici.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="yapay zeka" /><category term="Alan Turing" /><category term="makine öğrenmesi" /><summary type="html"><![CDATA[Yapay zekâ, makinelerin yalnızca hesap yapmasını değil; algılama, öğrenme, akıl yürütme ve karar verme gibi zekâyla ilişkilendirilen görevleri gerçekleştirmesini amaçlayan disiplinler arası bir alandır. Bugün sohbet botlarından otonom araçlara kadar her yerde karşımıza çıksa da bu yolculuk, “Makineler düşünebilir mi?” sorusuyla başladı.]]></summary></entry></feed>