Etiket: #teknoloji

  • Dosya Okuma ve Yazma (Python Dersi 14)

    Dosya Okuma ve Yazma (Python Dersi 14)

    Şimdiye kadar yazdığımız her programda bir sorun vardı: Program kapanınca her şey unutuluyordu. Sayı tahmin oyununda en iyi skorunu, alışveriş listende yazdığın ürünleri, hesapladığın notları… Hepsi değişkenlerde duruyordu ve değişkenler program bitince kaybolur.

    Bir şeyi kalıcı olarak saklamanın en basit yolu onu bir dosyaya yazmak. Bu derste dosya açmayı, yazmayı, okumayı ve veri analizinde en sık göreceğin CSV dosyalarını öğreniyoruz. Sonunda da kapatıp açınca bile unutmayan bir alışveriş listesi yazıyoruz.

    Tüm kodlar Colab’da, tek tıkla açılıyor: Colab’da aç

    Colab’da oluşturduğun dosyaları sol taraftaki klasör simgesine tıklayarak görebilirsin. Ama dikkat: Colab oturumu kapanınca bu dosyalar da silinir. Kalıcı saklamak istediğin bir dosyayı bilgisayarına indirmen gerekir.

    İlk dosyamızı yazalım

    open() fonksiyonu bir dosyayı açar. Ona iki şey söylüyoruz: dosyanın adı ve ne yapacağımız.

    dosya = open("notlar.txt", "w", encoding="utf-8")
    dosya.write("Bugün dosyalara giriş yaptım.\n")
    dosya.write("Şimdi ne öğrendiğimi okuyacağım.\n")
    dosya.close()
    print("Dosya yazıldı.")

    Satır satır ne oluyor:

    • "w": yazmak için aç (write). Dosya yoksa oluşturulur.
    • encoding="utf-8": ç, ğ, ı, ö, ş, ü gibi Türkçe karakterlerin doğru kaydedilmesi için. Bunu her dosya işleminde yazmayı alışkanlık hâline getir.
    • \n: satır sonu. Yazmazsan iki cümle aynı satıra yapışır.
    • close(): dosyayı kapat. Unutursan yazdıkların dosyaya tam kaydedilmeyebilir.

    with: kapatmayı Python’a bırak

    close() yazmayı unutmak çok kolay. with bloğu bu yükten kurtarıyor: Blok bitince dosya kendiliğinden kapanır. Bundan sonra hep bu yolu kullanacağız.

    with open("notlar.txt", "r", encoding="utf-8") as dosya:
    icerik = dosya.read()
    print(icerik)
    Bugün dosyalara giriş yaptım.
    Şimdi ne öğrendiğimi okuyacağım.

    "r" okumak (read) demek. read() dosyanın tamamını tek bir metin olarak getirir.

    Üç temel mod: r, w, a

    ModAnlamıDosya yoksaDosya varsa
    "r"okuhata verirbaştan okur
    "w"yazoluştururiçini siler, baştan yazar
    "a"ekleoluşturursonuna ekler

    En sık yapılan hata: Var olan bir dosyaya bir şey eklemek isterken "w" kullanmak. "w" dosyanın içini sorgusuz sualsiz siler. Eski içeriği korumak istiyorsan "a" (append) kullan:

    with open("notlar.txt", "a", encoding="utf-8") as dosya:
    dosya.write("Bu satır sonradan eklendi.\n")

    Satır satır okumak

    Dosyayı bir for döngüsüne verirsen her turda bir satır gelir:

    with open("notlar.txt", "r", encoding="utf-8") as dosya:
    for numara, satir in enumerate(dosya, start=1):
    print(numara, satir.strip())
    1 Bugün dosyalara giriş yaptım.
    2 Şimdi ne öğrendiğimi okuyacağım.
    3 Bu satır sonradan eklendi.

    Her satırın sonunda bir \n karışıyor. strip() onu atıyor; yoksa satırların arasında boş satırlar görürsün. enumerate ise satırları numaralandırmamızı sağlıyor.

    Tüm satırları bir listeye almak istersen:

    with open("notlar.txt", "r", encoding="utf-8") as dosya:
    satirlar = dosya.read().splitlines()
    print(len(satirlar)) # 3

    Sayıları yazmak: önce metne çevir

    write() sadece metin kabul eder. Bir sayıyı yazmadan önce str() ile metne çevirmen, okurken de int() ile geri sayıya çevirmen gerekir:

    puanlar = [85, 92, 78]
    with open("puanlar.txt", "w", encoding="utf-8") as dosya:
    for puan in puanlar:
    dosya.write(str(puan) + "\n")
    with open("puanlar.txt", "r", encoding="utf-8") as dosya:
    okunan = [int(satir) for satir in dosya]
    print(okunan) # [85, 92, 78]
    print(sum(okunan) / len(okunan)) # 85.0

    Okuma kısmındaki tek satırlık döngü, Ders 12’de öğrendiğimiz liste üreteci.

    Devamını oku: Kümeler ve Liste Üreteçleri (Python Dersi 12)

    Dosya yoksa ne olur?

    Olmayan bir dosyayı "r" ile açmaya çalışırsan Python FileNotFoundError verir ve program durur. Geçen derste öğrendiğimiz try ve except tam burada işe yarıyor:

    try:
    with open("olmayan_dosya.txt", "r", encoding="utf-8") as dosya:
    print(dosya.read())
    except FileNotFoundError:
    print("Böyle bir dosya yok. Önce oluşturman gerekiyor.")

    Devamını oku: Hata Yönetimi: try ve except (Python Dersi 13)

    CSV dosyaları

    Veri analizine geçtiğinde en sık göreceğin dosya türü CSV olacak. Her satır bir kayıt, değerler virgülle ayrılmış. Aslında düz bir metin dosyası, Excel’de de açılabiliyor. Python’un hazır csv modülü bu işi kolaylaştırıyor:

    import csv
    ogrenciler = [
    ["ad", "bolum", "not"],
    ["Ayşe", "Bilgisayar", 88],
    ["Mehmet", "Endüstri", 74],
    ["Zeynep", "Bilgisayar", 95],
    ]
    with open("ogrenciler.csv", "w", encoding="utf-8", newline="") as dosya:
    yazici = csv.writer(dosya)
    yazici.writerows(ogrenciler)

    newline="" bazı sistemlerde satırlar arasında fazladan boş satır oluşmasını engelliyor. CSV yazarken eklemeyi unutma.

    Okurken csv.DictReader her satırı bir sözlüğe çeviriyor, böylece sütunlara adıyla ulaşabiliyorsun:

    with open("ogrenciler.csv", "r", encoding="utf-8") as dosya:
    for satir in csv.DictReader(dosya):
    print(satir["ad"], "->", satir["not"])
    Ayşe -> 88
    Mehmet -> 74
    Zeynep -> 95

    Dikkat: CSV’den okunan her şey metin olarak gelir. satir["not"] bir sayı değil, "88" gibi bir metin. Hesap yapacaksan int() ile çevirmen gerekiyor.

    Gerçek bir veri projesinde CSV’leri genelde pandas kütüphanesiyle okuyoruz, ama arka planda olan şey tam olarak bu.

    Devamını oku: Futbol Veri Projesi 1: Maç Verisini Toplamak ve Temizlemek

    Mini proje: unutmayan alışveriş listesi

    Öğrendiklerimizi birleştirelim. Program her açıldığında listeyi dosyadan yüklesin, yeni ürün eklenince dosyaya kaydetsin:

    LISTE_DOSYASI = "alisveris.txt"
    def listeyi_yukle():
    try:
    with open(LISTE_DOSYASI, "r", encoding="utf-8") as dosya:
    return dosya.read().splitlines()
    except FileNotFoundError:
    return []
    def urun_ekle(urun):
    with open(LISTE_DOSYASI, "a", encoding="utf-8") as dosya:
    dosya.write(urun + "\n")
    def listeyi_goster():
    liste = listeyi_yukle()
    if not liste:
    print("Liste boş.")
    for sira, urun in enumerate(liste, start=1):
    print(f"{sira}. {urun}")
    listeyi_goster()
    urun_ekle("süt")
    urun_ekle("ekmek")
    urun_ekle("domates")
    print("---")
    listeyi_goster()
    Liste boş.
    ---
    1. süt
    2. ekmek
    3. domates

    Burada üç dersin bir araya geldiğini görüyorsun: fonksiyonlar (Ders 9), hata yönetimi (Ders 13) ve dosyalar. Dosya henüz yoksa listeyi_yukle() programı çökertmek yerine boş bir liste döndürüyor.

    Colab’da son hücreyi bir kez daha çalıştır: Ürünler iki kez eklenir. Çünkü liste artık programın içinde değil, dosyada duruyor. Programı kapatıp açsan da kaybolmuyor. Bu dersin bütün meselesi de bu.

    Alıştırmalar

    1. gunluk.txt adında bir dosya oluştur ve içine üç satır yaz. Sonra dosyayı okuyup kaç satır olduğunu ekrana yazdır.
    2. puanlar.txt dosyasına içini silmeden iki yeni puan ekle. Sonra en yüksek puanı bul.
    3. ogrenciler.csv dosyasını DictReader ile oku ve sadece Bilgisayar bölümündeki öğrencilerin not ortalamasını hesapla.
    4. Alışveriş listesine urun_sil(urun) fonksiyonu ekle. İpucu: Listeyi yükle, ürünü çıkar, kalanları "w" ile baştan yaz.

    Cevaplar not defterinin sonunda.

    Bu derste neler öğrendik?

    • open(dosya, mod, encoding="utf-8") bir dosyayı açar.
    • with bloğu dosyayı kendiliğinden kapatır.
    • "r" okur, "w" silip yazar, "a" sonuna ekler.
    • Dosyayı for ile gezersen satır satır okursun; strip() satır sonunu temizler.
    • write() sadece metin alır: Sayıları str() ile çevir.
    • Olmayan dosya FileNotFoundError verir; try ve except ile yakala.
    • CSV için csv.writer ve csv.DictReader kullan, okunan değerlerin metin olduğunu unutma.

    Sıradaki ders

    Bir sonraki derste Python’un gücünün asıl kaynağına geliyoruz: başkalarının yazdığı hazır kodları kullanmak. Bu derste import csv diyerek küçük bir tadımını aldık.

    Sıradaki ders: Modüller ve pip: Hazır Kütüphaneleri Kullanmak (Python Dersi 15)

  • Hata Yönetimi: try ve except (Python Dersi 13)

    Hata Yönetimi: try ve except (Python Dersi 13)

    Bu seride şimdiye kadar birçok hata gördük: ValueError, KeyError, TypeError… Her seferinde program olduğu yerde durdu ve kırmızı bir mesaj yazdı. Gerçek bir uygulamada bu kabul edilemez. Kullanıcı yanlış bir şey yazdı diye bir banka uygulamasının kapandığını düşün.

    Bu derste hataları yakalamayı, onlara anlaşılır bir cevap vermeyi ve gerektiğinde kendi hatamızı oluşturmayı öğreniyoruz.

    Kodların hepsi Colab’da hazır: Colab’da Aç

    Hatalar programı durdurur

    sayi = int("abc")
    print("Bu satır hiç çalışmaz.")
    # ValueError: invalid literal for int() with base 10: 'abc'

    Python’da bu tür hatalara istisna (exception) deniyor. Bir istisna oluştuğunda Python o anda yaptığı işi bırakıyor. Biz bir şey söylemedikçe de programı tamamen durduruyor.

    try ve except

    try:
    sayi = int("abc")
    print("Bu satır çalışmaz.")
    except ValueError:
    print("Bu bir sayı değil.")
    print("Program devam ediyor.")
    Bu bir sayı değil.
    Program devam ediyor.

    Okunuşu basit: “Şunu dene. Eğer ValueError olursa, onun yerine şunu yap.” try bloğunun içinde hata çıktığı anda geri kalan satırlar atlanıyor ve doğrudan except bloğuna geçiliyor. Sonra program kaldığı yerden devam ediyor.

    Farklı hatalar, farklı cevaplar

    Bir try bloğunun altına birden fazla except yazabilirsin. Her hata türüne ayrı bir cevap veriyorsun:

    def bol(a, b):
    try:
    sonuc = int(a) / int(b)
    except ValueError:
    return "Lütfen sayı gir."
    except ZeroDivisionError:
    return "Sıfıra bölünemez."
    return sonuc
    print(bol("10", "2")) # 5.0
    print(bol("on", "2")) # Lütfen sayı gir.
    print(bol("10", "0")) # Sıfıra bölünemez.

    En sık karşılaşacağın hatalar:

    HataNe zaman olur?Örnek
    ValueErrorDeğerin türü doğru ama içeriği uygun değilint("abc")
    TypeErrorİşlem bu türle yapılamıyor"5" + 3
    ZeroDivisionErrorSıfıra bölme10 / 0
    KeyErrorSözlükte olmayan anahtarnotlar["Zeynep"]
    IndexErrorListede olmayan sıra[1, 2, 3][10]
    FileNotFoundErrorAçılmak istenen dosya yokDers 14’te göreceğiz

    Hata mesajını yakalamak: as

    Hatanın ayrıntısını da kullanmak istersen as ile bir değişkene alabilirsin:

    notlar = {"Ayşe": 85, "Mert": 45}
    try:
    print(notlar["Zeynep"])
    except KeyError as hata:
    print("Bulunamayan anahtar:", hata)
    # Bulunamayan anahtar: 'Zeynep'

    Kod Kartı #06’da aynı durumu get() ile çözmüştük. İkisi de doğru; get kısa bir varsayılan değer için, try ise hata durumunda daha fazla şey yapman gerektiğinde daha uygun.

    else ve finally

    try bloğuna iki parça daha eklenebiliyor:

    def oku(metin):
    try:
    sayi = int(metin)
    except ValueError:
    print(f"{metin!r} sayıya çevrilemedi.")
    else:
    print(f"Başarılı: {sayi}")
    finally:
    print("Kontrol bitti.")
    oku("42")
    oku("kırk iki")
    Başarılı: 42
    Kontrol bitti.
    'kırk iki' sayıya çevrilemedi.
    Kontrol bitti.
    • else: Hiç hata olmazsa çalışır.
    • finally: Her durumda çalışır, hata olsa da olmasa da. Bir dosyayı kapatmak ya da bir bağlantıyı sonlandırmak gibi “ne olursa olsun yapılmalı” işler için kullanılır.

    {metin!r} ifadesi metni tırnaklarıyla yazdırıyor; boşluklu ya da boş bir girişi fark etmeyi kolaylaştırıyor.

    Kendi hatanı fırlatmak: raise

    Bazen Python için her şey doğru görünür ama senin programın için değildir. Mesela eksi bir yaş. Böyle durumlarda hatayı kendin oluşturabilirsin:

    def yas_kaydet(yas):
    if yas < 0:
    raise ValueError("Yaş negatif olamaz.")
    return f"Yaş kaydedildi: {yas}"
    try:
    yas_kaydet(-3)
    except ValueError as hata:
    print("Hata:", hata)
    # Hata: Yaş negatif olamaz.

    raise ile fırlatılan bir hata, Python’un kendi hataları gibi davranıyor: Yakalanmazsa programı durduruyor, yakalanırsa except bloğuna gidiyor.

    Kötü bir alışkanlık: her hatayı susturmak

    except yanına hata türü yazmazsan her hatayı yakalar. İlk bakışta pratik görünüyor ama tehlikeli:

    # Bunu yapma
    def ortalama_kotu(notlar):
    try:
    return sum(notlar) / len(notlar)
    except:
    return 0
    print(ortalama_kotu([])) # 0
    print(ortalama_kotu("doksan")) # 0

    Boş liste için 0 dönmesi belki kabul edilebilir. Ama ikinci satırda yanlış türde bir veri gönderdik ve fonksiyon bunu sessizce 0’a çevirdi. Gerçek bir programda bu tür hataları bulmak günler sürebilir. Kural: Sadece beklediğin ve ne yapacağını bildiğin hatayı yakala.

    # Bunu yap
    def ortalama(notlar):
    try:
    return sum(notlar) / len(notlar)
    except ZeroDivisionError:
    return None

    Bu sürüm boş listeyi yakalıyor, yanlış türde veri gelirse ise hatayı görmeni sağlıyor.

    Mini program: güvenli not girişi

    Ders 10’daki sayı tahmin oyununda kullanıcı girişini isdigit() ile kontrol etmiştik. Bu yöntem eksi sayıları ve ondalıklı sayıları da “rakam değil” diye reddediyordu. try ile daha sağlam bir sürüm yazalım:

    def not_iste(mesaj):
    """0 ile 100 arasında bir not alana kadar sorar."""
    while True:
    cevap = input(mesaj)
    try:
    puan = float(cevap.replace(",", "."))
    except ValueError:
    print("Lütfen bir sayı yaz.")
    continue
    if 0 <= puan <= 100:
    return puan
    print("Not 0 ile 100 arasında olmalı.")
    notlar = [not_iste(f"{i}. not: ") for i in range(1, 4)]
    print("Ortalama:", round(sum(notlar) / len(notlar), 1))
    1. not: doksan
    Lütfen bir sayı yaz.
    1. not: -5
    Not 0 ile 100 arasında olmalı.
    1. not: 85
    2. not: 70,5
    3. not: 101
    Not 0 ile 100 arasında olmalı.
    3. not: 90
    Ortalama: 81.8

    replace(",", ".") satırına dikkat: Türkiye’de ondalık sayıları virgülle yazıyoruz, Python ise nokta bekliyor. Kullanıcı “70,5” yazdığında virgülü noktaya çevirip öyle deniyoruz. Ders 11’deki Türkçe I/İ tuzağı gibi, bu da Türkçe kullanıcılar için yazılan programların küçük ama önemli bir detayı.

    Son satırdaki liste üreteci de Ders 12’den: not_iste fonksiyonunu üç kez çağırıp sonuçları bir listeye topluyor.

    Alıştırmalar

    1. Kullanıcıdan iki sayı alıp birinciyi ikinciye bölen bir program yaz. Sayı olmayan girişte ve sıfıra bölmede anlaşılır bir mesaj ver.
    2. ["10", "yirmi", "30", "", "40"] listesindeki metinleri tam sayıya çevir; çevrilemeyenleri atla ve kaç tanesinin atlandığını yazdır.
    3. Bir sözlükte anahtarı arayan bul(sozluk, anahtar) fonksiyonunu get kullanmadan, try ve except KeyError ile yaz.
    4. sifre_kontrol(sifre) fonksiyonu yaz: Şifre 8 karakterden kısaysa ValueError fırlatsın. Fonksiyonu bir kısa bir uzun şifreyle dene.

    Cevaplar Colab not defterinin sonunda.

    Bu derste ne öğrendik?

    • Bir istisna oluştuğunda Python programı durdurur; try ve except ile bunu yakalarız.
    • Farklı hata türleri için ayrı except blokları yazılabilir; as ile hata mesajına ulaşılır.
    • else hata olmazsa, finally her durumda çalışır.
    • raise ile kendi hatamızı fırlatabiliriz.
    • Sadece beklediğin hatayı yakala; türsüz except hataları saklar.

    Sıradaki ders

    Python Dersi 14’te dosya okumayı ve yazmayı öğreniyoruz. Bu derste öğrendiğin try ve except, olmayan bir dosyayı açmaya çalıştığında hemen işine yarayacak.

    Devamını oku

  • R ve RStudio Kurulumu (R Dersi 2)

    R ve RStudio Kurulumu (R Dersi 2)

    R Dersi 1’de R’ın ne olduğunu ve Python’dan nerede ayrıldığını konuştuk. Bu derste R’ı kendi bilgisayarına kuruyoruz. Aslında iki şey kuracağız: R ve RStudio. Baştan bu farkı anlamak, kurulumda karşılaşılan sorunların çoğunu önlüyor.

    R ile RStudio aynı şey değil

    • R dilin kendisi. Yazdığın kodu anlayıp çalıştıran program bu.
    • RStudio R’la çalışmayı kolaylaştıran bir geliştirme ortamı. Kod yazdığın editörü, grafiklerin göründüğü paneli, değişkenlerinin listesini bir arada sunuyor.

    Bir araba benzetmesi: R motor, RStudio da direksiyonu, göstergeleri ve koltuğuyla arabanın içi. Motor olmadan araba gitmez; iç olmadan da motoru kullanmak çok zor. Bu yüzden sıra önemli: önce R, sonra RStudio.

    Python derslerinde benzer bir ayrım vardı: Python dilin kendisi, Colab ise onu kullandığımız ortamdı.

    Bu seride biz ne kullanacağız? Python derslerinde olduğu gibi R derslerinde de Google Colab‘la devam edeceğiz. Yani bu serideki kodları çalıştırmak için bilgisayarına hiçbir şey kurman gerekmiyor. Yine de R’la ileride ciddi çalışmak, tez ya da proje yapmak isteyenler için kurulumu da adım adım anlatıyorum. Kurulumu şimdilik atlamak istiyorsan doğrudan “Bizim sistemimiz: R’ı Colab’da kullanmak” bölümüne geçebilirsin.

    1. Adım: R’ı kur

    R, CRAN (Comprehensive R Archive Network) üzerinden ücretsiz dağıtılıyor: cloud.r-project.org

    Windows

    1. cloud.r-project.org adresine git ve “Download R for Windows” bağlantısına tıkla.
    2. “base” bağlantısına tıkla, sonra en üstteki “Download R-4.x.x for Windows” bağlantısından kurulum dosyasını indir. Numara güncel sürüme göre değişir.
    3. Dosyayı çalıştır ve varsayılan ayarlarla “İleri” diyerek kurulumu bitir.

    Aynı sayfada göreceğin Rtools‘a şimdilik ihtiyacın yok. Rtools bazı paketleri kaynak koddan derlemek için gerekiyor; yeni başlarken kullandığın paketlerin neredeyse hepsi hazır derlenmiş geliyor.

    macOS

    1. cloud.r-project.org adresine git ve “Download R for macOS” bağlantısına tıkla.
    2. Mac’inin işlemcisine uygun dosyayı seç: Apple Silicon (M1, M2, M3 ve sonrası) için “arm64”, Intel işlemcili Mac’ler için “x86_64” yazan dosya. Hangisi olduğunu sol üstteki elma menüsünden “Bu Mac Hakkında” bölümünde görebilirsin.
    3. İndirdiğin .pkg dosyasını aç ve kurulumu tamamla.

    Kurulumu kontrol et

    R’ı açtığında sade bir konsol penceresi göreceksin. > işaretinin yanına şunu yaz ve Enter’a bas:

    1 + 1

    [1] 2 yazıyorsa R çalışıyor. Bu pencereyi kapatabilirsin; bundan sonra R’ı RStudio’nun içinden kullanacağız.

    2. Adım: RStudio’yu kur

    RStudio’yu Posit firması geliştiriyor. Ücretsiz ve açık kaynaklı sürümün adı RStudio Desktop. “Pro” yazan sürüm şirketler için olan ücretli sürüm; ona ihtiyacın yok.

    1. posit.co adresinde RStudio Desktop’ın indirme sayfasını aç.
    2. Sayfa işletim sistemini genelde kendisi tanır ve uygun dosyayı önerir. Windows için .exe, macOS için .dmg dosyasını indir.
    3. Windows’ta .exe dosyasını çalıştır. macOS’ta .dmg dosyasını aç ve RStudio simgesini Uygulamalar klasörüne sürükle.
    4. RStudio’yu aç. Bilgisayarındaki R’ı kendisi bulacak.

    Posit’in güncel indirme sayfasına göre RStudio Desktop; Windows 11, macOS 15 ve sonrası ile yaygın Linux dağıtımlarında çalışıyor. Daha eski bir sistem kullanıyorsan aşağıdaki kurulumsuz seçeneklere bak.

    RStudio’yu tanı: dört panel

    RStudio’yu ilk açtığında ekran dört bölüme ayrılıyor. İlk açılışta sol üstteki panel görünmeyebilir; yeni bir dosya açınca ortaya çıkıyor.

    PanelYeriNe işe yarar?
    Source (Kaynak)Sol üstKodunu yazdığın ve kaydettiğin dosyalar
    Console (Konsol)Sol altKodun çalıştığı ve sonuçların yazıldığı yer
    Environment (Ortam)Sağ üstOluşturduğun değişkenlerin ve tabloların listesi
    Files, Plots, Packages, HelpSağ altDosyalar, grafikler, kurulu paketler ve yardım sayfaları

    Konsola yazdığın kod hemen çalışır ama kaydedilmez. Saklamak istediğin her şeyi Source panelinde bir dosyaya yaz.

    İlk R dosyan

    1. Üst menüden File > New File > R Script seç. Sol üstte boş bir dosya açılacak.
    2. Şu satırları yaz:
    # Benim ilk R dosyam
    notlar <- c(70, 85, 40, 90, 45)
    mean(notlar)
    hist(notlar, main = "Not dağılımı", col = "steelblue")
    1. İmleci ilk satırlardan birine getir ve Ctrl + Enter (Mac’te Cmd + Enter) bas. O satır konsolda çalışır. Satır satır ilerle.
    2. Son satırı çalıştırınca sağ alttaki Plots panelinde notların dağılımını gösteren bir grafik belirecek. Sağ üstteki Environment panelinde de notlar değişkenini göreceksin.
    3. Ctrl + S (Mac’te Cmd + S) ile dosyayı kaydet. R dosyalarının uzantısı .R.

    Dosyanın tamamını tek seferde çalıştırmak için Source panelinin sağ üstündeki Source düğmesini kullanabilirsin.

    Paket kurmak

    R’ın gücünün büyük kısmı paketlerden geliyor. Bir paketi bilgisayarına bir kez kuruyorsun, her yeni oturumda da yüklüyorsun:

    install.packages("ggplot2") # bir kez: paketi indirip kurar
    library(ggplot2) # her oturumda: paketi kullanıma açar

    install.packages içinde paket adı tırnak içinde, library içinde tırnaksız yazılıyor. ggplot2’yu ilerideki derslerde grafik çizmek için kullanacağız. Python’daki pip install ve import ikilisinin R’daki karşılığı bu; Python tarafını Ders 15’te anlatacağım.

    Bir fonksiyonun ne yaptığını merak edersen başına soru işareti koy:

    ?mean

    Yardım sayfası sağ alttaki Help panelinde açılır.

    İyi bir alışkanlık: RStudio projesi

    Her ders ya da çalışma için ayrı bir proje açmak, dosyalarını düzenli tutmanın en kolay yolu:

    1. File > New Project > New Directory > New Project seç.
    2. Proje adını yaz (örneğin r-dersleri) ve klasörün yerini seç.

    RStudio bu klasörü çalışma dizini yapar. Bir veri dosyasını proje klasörüne koyduğunda, dosyayı uzun bir yol yazmadan sadece adıyla okuyabilirsin.

    Bizim sistemimiz: R’ı Colab’da kullanmak

    Bu serinin bütün kodlarını Python derslerinde kullandığımız Google Colab’da çalıştıracağız. Colab’ı Python Dersi 2’den tanıyorsun; R için tek fark çalışma zamanını değiştirmek.

    1. colab.research.google.com adresine git ve Google hesabınla giriş yap.
    2. Dosya > Yeni not defteri ile boş bir not defteri aç.
    3. Üst menüden Çalışma zamanı > Çalışma zamanı türünü değiştir seç.
    4. Açılan pencerede dil olarak R‘ı seç ve kaydet.
    5. İlk hücreye R.version.string yaz ve Shift + Enter ile çalıştır. Çıktıda R’ın sürümünü görüyorsan hazırsın.

    Yukarıdaki “İlk R dosyan” bölümündeki kodu da aynı şekilde bir hücreye yapıştırıp çalıştırabilirsin; grafik hücrenin hemen altında görünür.

    Colab’da çalışırken bilmen gereken üç şey:

    • Kopyanı kaydet. Python derslerindeki gibi, çalışmanı saklamak için Dosya > Drive’da kopya kaydet seç.
    • Paketler kalıcı değil. Colab her yeni oturumda temiz bir makineyle başlıyor. install.packages ile kurduğun bir paketi ertesi gün yeniden kurman gerekebilir. Bu yüzden paket kuran satırları not defterinin en üstündeki hücrede tut.
    • Dosyalar kalıcı değil. Sol taraftaki dosya panelinden yüklediğin bir veri dosyası da oturum kapanınca siliniyor. Kalıcı olması gereken dosyaları Google Drive’ında tut.

    Colab dışında kurulum gerektirmeyen bir seçenek daha var: Posit Cloud, RStudio’nun tarayıcıda çalışan sürümü. RStudio’nun dört panelli görünümünü kurulum yapmadan denemek istersen oraya da bakabilirsin. Bu serideki kodların hepsi Colab’da, RStudio’da ve Posit Cloud’da aynı şekilde çalışıyor.

    Sık karşılaşılan sorunlar

    • “RStudio R’ı bulamıyor” uyarısı: Büyük ihtimalle R kurulmadan RStudio kuruldu. R’ı kur ve RStudio’yu yeniden başlat.
    • Paket kurulurken “Would you like to use a personal library?” sorusu: “Yes” de. Paket, bilgisayarın sistem klasörü yerine senin kullanıcı klasörüne kurulur; bu normal.
    • Windows’ta kullanıcı adında Türkçe karakter: Kullanıcı klasörünün adında ş, ı, ö gibi harfler varsa bazı paketlerin kurulumunda sorun çıkabiliyor. Başına gelirse bir proje klasörünü Türkçe karakter içermeyen bir yola (örneğin C:\r-dersleri) açmak iyi bir ilk adım.
    • Hangi sürümü kurduğunu görmek: Konsola R.version.string yaz.

    Bu derste ne öğrendik?

    • R dilin kendisi, RStudio onu kullandığımız ortam. Önce R, sonra RStudio kurulur.
    • R, CRAN’dan; RStudio Desktop, Posit’in sitesinden ücretsiz indirilir.
    • RStudio’da dört panel var: kaynak, konsol, ortam ve dosyalar/grafikler/yardım.
    • Ctrl + Enter (Mac’te Cmd + Enter) bulunduğun satırı çalıştırır.
    • Paketler bir kez install.packages ile kurulur, her oturumda library ile yüklenir.
    • Bu seride kodları Google Colab’ın R çalışma zamanında çalıştıracağız; kurulum isteyene kaldı.

    Sıradaki ders

    R Dersi 3’te R’da değişkenleri ve veri tiplerini öğreniyoruz. Python Dersi 3’ü okuduysan birçok şey tanıdık gelecek.

    Devamını oku

  • Harry Potter’ın Seçmen Şapkası: Basit Bir Sınıflandırma Modeli

    Harry Potter’ın Seçmen Şapkası: Basit Bir Sınıflandırma Modeli

    Hogwarts’a gelen her öğrenci başına eski bir şapka takıyor ve şapka birkaç saniye içinde karar veriyor: Gryffindor, Ravenclaw, Hufflepuff ya da Slytherin. Bir veri bilimci gözüyle bakınca Seçmen Şapkası aslında bir sınıflandırma modeli: girdi olarak bir öğrenciyi alıyor, çıktı olarak dört etiketten birini veriyor.

    Bu yazıda kendi şapkamızı iki kez kuracağız. Önce elle yazılmış kurallarla, sonra örneklerden öğrenen bir karar ağacıyla. Yolda makine öğreniminin üç temel fikrine değeceğiz: eğitim ve test verisi, modelin nerede yanıldığını görmek ve aşırı öğrenme.

    Hogwarts Legacy oyununda şapka beni Ravenclaw’a göndermişti. Bu yazı için de aklımdaki soru şuydu: Bu kararı bir model verseydi, neye bakarak verirdi?

    Kodların hepsi Colab’da hazır, kurulum gerekmiyor: Colab’da Aç

    Veri hakkında: Yazıdaki öğrencilerin hepsi hayali. Veriyi kod kendisi üretiyor; kitaplardan ya da filmlerden hiçbir karakter, metin veya görsel kullanmıyoruz.

    Şapkaya ne soruyoruz?

    Her öğrenciyi dört özellikle tarif edelim ve her birine 0 ile 10 arasında puan verelim: cesaret, zeka, sadakat ve hırs. Her binanın öne çıkardığı bir özellik var: Gryffindor cesareti, Ravenclaw zekayı, Hufflepuff sadakati, Slytherin hırsı.

    Makine öğrenimi dilinde bu dört puan öznitelik (feature), bina adı ise etiket (label). Modelin işi özniteliklere bakıp etiketi tahmin etmek.

    1. Kural tabanlı şapka

    En akla yatkın kural: öğrencinin en yüksek özelliğine bak, o özelliğin binasına gönder.

    OZELLIKLER = ["cesaret", "zeka", "sadakat", "hirs"]
    BINALAR = {"Gryffindor": "cesaret", "Ravenclaw": "zeka",
    "Hufflepuff": "sadakat", "Slytherin": "hirs"}
    def kural_sapka(ogrenci):
    """En yüksek puanlı özelliğe bakıp binayı seçer."""
    en_guclu = max(OZELLIKLER, key=lambda o: ogrenci[o])
    for bina, ozellik in BINALAR.items():
    if ozellik == en_guclu:
    return bina
    print(kural_sapka({"cesaret": 9, "zeka": 6, "sadakat": 7, "hirs": 4}))
    # Gryffindor
    print(kural_sapka({"cesaret": 5.2, "zeka": 5.4, "sadakat": 5.1, "hirs": 5.3}))
    # Ravenclaw

    İlk öğrencide sorun yok. İkincisine bak: dört özelliği de neredeyse eşit, zekası sadece 0,1 puan önde diye Ravenclaw’a gidiyor. Kuralın bu öğrenci hakkında “emin değilim” deme imkanı yok. İnsan eliyle yazılan kuralların genel derdi bu: düşündüğün durumlarda çalışıyor, düşünmediğin durumlarda sessizce yanılıyor.

    max satırındaki key=lambda o: ogrenci[o] ifadesi, “özellik adlarını karşılaştırırken her birinin puanına bak” demek. Fonksiyonları bugünkü Python Dersi 9’da anlattım; lambda ise tek satırlık, isimsiz bir fonksiyon.

    2. Hayali öğrenciler üretmek

    Model örneklerden öğreneceği için bize etiketli veri lazım. Her binadan 60, toplam 240 hayali öğrenci üretelim. Gryffindor, Ravenclaw ve Slytherin öğrencilerinde binanın özelliği belirgin şekilde yüksek olsun.

    Hufflepuff’a bir büküm ekleyelim. Hufflepuff, kapısını herkese açan bina olarak bilinir. Bu yüzden öğrencilerin yarısında sadakat yüksek, diğer yarısında ise hiçbir özellik öne çıkmıyor. Kural tabanlı şapka bu ikinci grubu bilmiyor; bakalım model fark edebilecek mi?

    import numpy as np
    import pandas as pd
    rng = np.random.default_rng(42)
    satirlar = []
    for bina, baskin in BINALAR.items():
    for i in range(60):
    if bina == "Hufflepuff" and i % 2 == 1:
    # Dengeli öğrenci: hiçbir özellik öne çıkmıyor
    ogr = {o: rng.normal(5, 0.7) for o in OZELLIKLER}
    ogr["sadakat"] = rng.normal(5.5, 0.7)
    else:
    ogr = {o: rng.normal(4.5, 1.2) for o in OZELLIKLER}
    ogr[baskin] = rng.normal(8, 1)
    ogr = {o: float(np.clip(round(v, 1), 0, 10)) for o, v in ogr.items()}
    ogr["bina"] = bina
    satirlar.append(ogr)
    df = pd.DataFrame(satirlar)
    print(df.groupby("bina")[OZELLIKLER].mean().round(1))
                cesaret  zeka  sadakat  hirs
    bina
    Gryffindor      7.8   4.4      4.5   4.6
    Hufflepuff      4.8   4.9      6.5   4.4
    Ravenclaw       4.3   8.1      4.6   4.3
    Slytherin       4.6   4.6      4.5   7.8

    rng.normal(8, 1), ortalaması 8 olan ve çoğunlukla 7 ile 9 arasına düşen rastgele bir sayı üretiyor. np.clip puanları 0 ile 10 arasında tutuyor. default_rng(42) içindeki 42 sayesinde kodu her çalıştırdığında aynı öğrenciler üretiliyor, böylece sen de yazıdaki sonuçların aynısını görüyorsun.

    3. Eğitim ve test verisi

    Bir modeli, öğrendiği örneklerle sınamak sınavdan önce cevap anahtarını vermeye benzer. Bu yüzden veriyi ikiye ayırıyoruz: model 180 öğrenciden öğrenecek, hiç görmediği 60 öğrenciyle sınanacak.

    from sklearn.model_selection import train_test_split
    from sklearn.metrics import accuracy_score
    X = df[OZELLIKLER]
    y = df["bina"]
    X_egitim, X_test, y_egitim, y_test = train_test_split(
    X, y, test_size=0.25, random_state=42, stratify=y
    )
    kural_tahmin = [kural_sapka(ogr) for ogr in X_test.to_dict("records")]
    print(f"Kural tabanlı şapkanın doğruluğu: {accuracy_score(y_test, kural_tahmin):.0%}")
    # Kural tabanlı şapkanın doğruluğu: 83%

    stratify=y, test grubunda her binadan eşit sayıda (15’er) öğrenci olmasını sağlıyor. Kural tabanlı şapka 60 test öğrencisinin 50’sini doğru yerleştirdi. Kötü değil; şimdi bunu geçmeye çalışalım.

    4. Karar ağacı: şapkaya örneklerden öğretmek

    Karar ağacı, veriye bakıp kendi evet-hayır sorularını oluşturan bir model. “Zeka 6,35’ten büyük mü?” diye sorar, cevaba göre bir dala geçer, sonra yeni bir soru sorar. Yani yaptığı şey bizim if-else kuralımıza çok benziyor; farkı, kuralları bizim yerimize veriden çıkarması.

    from sklearn.tree import DecisionTreeClassifier, export_text
    model = DecisionTreeClassifier(max_depth=3, random_state=42)
    model.fit(X_egitim, y_egitim)
    tahmin = model.predict(X_test)
    print(f"Karar ağacının doğruluğu: {accuracy_score(y_test, tahmin):.0%}")
    # Karar ağacının doğruluğu: 88%

    max_depth=3, ağacın en fazla üç soru üst üste sorabileceği anlamına geliyor. fit öğrenme adımı, predict tahmin adımı. Ağaç 60 öğrencinin 53’ünü doğru yerleştirdi.

    Karar ağacının güzel tarafı, öğrendiği kuralları okuyabilmemiz:

    print(export_text(model, feature_names=OZELLIKLER))
    |--- zeka <= 6.35
    | |--- hirs <= 6.45
    | | |--- cesaret <= 5.85
    | | | |--- class: Hufflepuff
    | | |--- cesaret > 5.85
    | | | |--- class: Gryffindor
    | |--- hirs > 6.45
    | | |--- cesaret <= 8.30
    | | | |--- class: Slytherin
    | | |--- cesaret > 8.30
    | | | |--- class: Gryffindor
    |--- zeka > 6.35
    | |--- hirs <= 7.30
    | | |--- cesaret <= 7.50
    | | | |--- class: Ravenclaw
    | | |--- cesaret > 7.50
    | | | |--- class: Gryffindor
    | |--- hirs > 7.30
    | | |--- class: Slytherin

    Bu çıktıdaki en ilginç detay şu: ağaç sadakati hiç sormuyor. Hufflepuff’ı “zekası, hırsı ve cesareti yüksek olmayan öğrenci” diye tarif ediyor. Biz veriyi üretirken Hufflepuff’ın yarısını dengeli öğrencilerden oluşturmuştuk; model de bunu bulmuş ve öteki üç binaya girmeyenleri Hufflepuff’a gönderen bir kural çıkarmış. Kural tabanlı şapkanın bilmediği şeyi örneklerden öğrendi.

    5. Şapka nerede yanılıyor?

    Doğruluk tek bir sayı; hangi binaların karıştığını söylemiyor. Bunun için karışıklık matrisine (confusion matrix) bakıyoruz. Satırlar gerçek binayı, sütunlar modelin tahminini gösteriyor:

    Gerçek \ TahminGryffindorRavenclawHufflepuffSlytherin
    Gryffindor14001
    Ravenclaw11400
    Hufflepuff13110
    Slytherin00114

    Köşegendeki sayılar doğru tahminler. Hataların çoğu Hufflepuff satırında: 15 Hufflepuff öğrencisinin 3’ü Ravenclaw’a gitmiş. Bunlar büyük ihtimalle zekası biraz yüksek çıkan dengeli öğrenciler. Gerçek bir projede bir sonraki adım bu örneklere tek tek bakmak olurdu.

    6. Ağacı büyütmek her zaman iyi mi?

    Derinlik 3 yerine 10 olsa daha mı iyi olur? Farklı derinlikleri deneyip hem eğitim hem test doğruluğuna bakalım:

    for d in [1, 2, 3, 4, 5, 6, 8, 10]:
    m = DecisionTreeClassifier(max_depth=d, random_state=42).fit(X_egitim, y_egitim)
    egitim = accuracy_score(y_egitim, m.predict(X_egitim))
    test = accuracy_score(y_test, m.predict(X_test))
    print(f"derinlik {d:>2}: eğitim {egitim:.0%}, test {test:.0%}")
    derinlik 1: eğitim 49%, test 47%
    derinlik 2: eğitim 72%, test 67%
    derinlik 3: eğitim 94%, test 88%
    derinlik 4: eğitim 97%, test 90%
    derinlik 5: eğitim 98%, test 90%
    derinlik 6: eğitim 99%, test 90%
    derinlik 8: eğitim 100%, test 90%
    derinlik 10: eğitim 100%, test 90%

    Derinlik 8’de ağaç eğitim verisindeki her öğrenciyi doğru yerleştiriyor, ama yeni öğrencilerde derinlik 4’ten hiç daha iyi değil. Ekstra sorular genel bir kural öğrenmiyor, eğitimdeki tek tek öğrencileri ezberliyor. Buna aşırı öğrenme (overfitting) deniyor ve makine öğreniminde eğitim puanına tek başına güvenmememizin sebebi bu. Bizim örneğimizde zararı yok gibi görünüyor; daha gürültülü gerçek verilerde ise ezberleyen model test puanını da düşürebilir. Derinlik 3 de 4’e çok yakın sonuç veriyor ve kuralları bir bakışta okunabiliyor; yazıda bu yüzden onu seçtim.

    7. Berabere kalınca ne olur?

    Model, tahminin yanında her bina için bir olasılık da veriyor. Bunu bir fonksiyona saralım:

    def sapka(cesaret, zeka, sadakat, hirs):
    ogr = pd.DataFrame([{"cesaret": cesaret, "zeka": zeka, "sadakat": sadakat, "hirs": hirs}])
    olasiliklar = model.predict_proba(ogr)[0]
    for bina, p in sorted(zip(model.classes_, olasiliklar), key=lambda x: -x[1]):
    if p > 0:
    print(f"{bina:<11} {p:.0%}")
    print("Şapkanın kararı:", model.predict(ogr)[0])
    sapka(cesaret=9, zeka=5, sadakat=4, hirs=5)
    Gryffindor 89%
    Hufflepuff 9%
    Slytherin 2%
    Şapkanın kararı: Gryffindor

    Şimdi cesareti ve hırsı tam olarak eşit bir öğrenci deneyelim:

    berabere = {"cesaret": 8, "zeka": 5, "sadakat": 5, "hirs": 8}
    print("Kural tabanlı şapka:", kural_sapka(berabere))
    sapka(**berabere)
    Kural tabanlı şapka: Gryffindor
    Slytherin 98%
    Hufflepuff 2%
    Şapkanın kararı: Slytherin

    İki şapka iki farklı binayı seçti ve ikisinin de sebebi ilginç. Kural tabanlı şapka Gryffindor diyor, çünkü max eşitlikte listede önce gelen özelliği seçiyor. Yani kararı öğrenci değil, benim listeyi yazma sıram verdi. Karar ağacı ise %98 eminlikle Slytherin diyor, çünkü kurallarından biri “hırs yüksekse ve cesaret 8,30’u geçmiyorsa Slytherin”.

    Buradan çıkacak ders şu: Modelin %98 demesi gerçekten bu kadar emin olduğu anlamına gelmiyor. Karar ağacı olasılığı, öğrencinin düştüğü yapraktaki eğitim örneklerinin oranından hesaplıyor. O yaprakta neredeyse hep Slytherin öğrencileri olduğu için sayı yüksek çıkıyor. Tam sınırdaki bir öğrenci için bile. Olasılık çıktısını okurken bunu akılda tutmak gerekiyor.

    8. Kendi şapkanı tak

    Not defterinin sonunda dört soruluk küçük bir test var. Her özelliğe kendine 0 ile 10 arası puan veriyorsun, şapka da kararını ve olasılıkları yazıyor:

    puanlar = {}
    for o in OZELLIKLER:
    puanlar[o] = float(input(f"{o} (0-10): "))
    sapka(**puanlar)

    sapka(**puanlar) satırındaki iki yıldız, sözlükteki anahtarları isimli argümanlara çeviriyor. Yani sapka(cesaret=..., zeka=..., ...) yazmakla aynı şey.

    Bu projede ne öğrendik?

    • Sınıflandırma: özniteliklere bakıp bir etiket tahmin etmek.
    • Kural tabanlı sistemler düşündüğün durumlarda çalışır; örneklerden öğrenen model, senin görmediğin kalıpları bulabilir.
    • Modeli her zaman görmediği verilerle sına.
    • Karışıklık matrisi, hatanın nerede olduğunu gösterir.
    • Eğitim puanı yüzde 100 olan model iyi bir model olmayabilir; aşırı öğrenmeye dikkat.
    • Olasılık çıktısı her zaman gerçek bir eminlik ölçüsü değil.

    Kendin dene

    1. max_depth değerini 2 ve 5 yapıp kuralların nasıl değiştiğine bak.
    2. default_rng(42) içindeki 42’yi değiştir. Sonuçlar ne kadar oynuyor?
    3. Veriye beşinci bir özellik ekle (örneğin merak) ve hangi binada yüksek olacağına sen karar ver.
    4. Karar ağacı yerine KNeighborsClassifier(n_neighbors=5) dene ve olasılıkların nasıl değiştiğini karşılaştır.

    Devamını oku

  • Kod Kartı: Sözlükte Olmayan Anahtar: get() Kullan

    Kod Kartı: Sözlükte Olmayan Anahtar: get() Kullan

    Sözlükte olmayan bir anahtarı köşeli parantezle istersen Python programı durdurur: KeyError. Kullanıcıdan gelen bir isim, bir dosyadan okunan bir sütun ya da bir API’den dönen bir alan; hepsi “bu anahtar orada olmayabilir” durumları. get() bu durumda programı durdurmak yerine sana bir varsayılan değer verir.

    Kod

    notlar = {"Ayşe": 85, "Mert": 45}
    print(notlar["Zeynep"]) # KeyError: 'Zeynep'
    print(notlar.get("Zeynep")) # None
    print(notlar.get("Zeynep", 0)) # 0
    print(notlar) # {'Ayşe': 85, 'Mert': 45}

    get iki şey alıyor: aranan anahtar ve anahtar yoksa dönecek değer. İkincisini yazmazsan None döner. Son satıra dikkat: get sözlüğe hiçbir şey eklemiyor, sadece okuyor.

    En sık kullanımı: sayaç

    Python Dersi 8’deki kelime sayacını hatırla:

    oylar = ["elma", "muz", "elma"]
    sayac = {}
    for oy in oylar:
    sayac[oy] = sayac.get(oy, 0) + 1
    print(sayac) # {'elma': 2, 'muz': 1}

    Bir meyve ilk kez görüldüğünde sözlükte yok, get 0 veriyor, üstüne 1 ekleniyor. Sonraki seferlerde mevcut sayı geliyor. get olmasaydı her seferinde if oy in sayac: diye kontrol etmek gerekirdi.

    Dikkat: anahtar var ama değeri None

    Varsayılan değer sadece anahtar hiç yoksa devreye girer. Anahtar varsa, değeri None bile olsa o döner:

    ayarlar = {"tema": None}
    print(ayarlar.get("tema", "açık")) # None, "açık" değil!
    print(ayarlar.get("dil", "tr")) # tr

    Veriyi bir yerden okurken boş alanlar sık sık None olarak gelir. “Yoksa ya da boşsa varsayılanı kullan” demek istiyorsan bunu ayrıca kontrol etmen gerekiyor.

    Ne zaman get(), ne zaman köşeli parantez?

    • Anahtarın mutlaka olması gerekiyorsa sözlük[anahtar] kullan. Yoksa ortada bir hata vardır ve KeyError bunu sana hemen söyler.
    • Anahtarın olmaması normalse get kullan ve mantıklı bir varsayılan ver.

    get her hatayı susturmak için değil. Yanlış yazılmış bir anahtarı ("Ayse" yerine "Ayşe") sessizce 0’a çevirirse hatayı bulmak çok daha zorlaşır.

    Sözlükleri Python Dersi 8’de, fonksiyonları ve varsayılan değerleri Python Dersi 9’da anlattım.

  • Black Mirror’daki Teknolojiler: Hangileri Gerçek Oldu?

    Black Mirror’daki Teknolojiler: Hangileri Gerçek Oldu?

    Black Mirror’ın her bölümü aynı soruyla biter: “Bu teknoloji gerçek olsa ne olurdu?” Dizinin ilk bölümlerinin üzerinden on yıldan fazla geçti ve bu sorunun cevabı bazı bölümler için artık bir tahmin değil, haber başlığı. Bu yazıda dizinin altı teknolojisini gerçek dünyadaki karşılıklarıyla yan yana koydum ve her birine bir not verdim: gerçek oldu, kısmen gerçek ya da henüz değil.

    Spoiler uyarısı: Bölümlerin ana fikirlerinden bahsediyorum ama sonlarını anlatmıyorum.

    1. Ölen birini yapay zekâyla geri getirmek (“Be Right Back”)

    Dizide: Sevgilisini kaybeden bir kadın, onun sosyal medya paylaşımlarından ve mesajlarından öğrenen bir yazılımla konuşmaya başlıyor.

    Gerçekte: Yazılımcı Eugenia Kuyda, yakın arkadaşı Roman bir trafik kazasında hayatını kaybettikten sonra, onunla yaptığı mesajlaşmaları bir yapay zekâ programına verdi ve onun konuşma tarzını taklit eden bir sohbet botu yaptı. Bu deneyim, bugün milyonlarca kullanıcısı olan sohbet arkadaşı uygulaması Replika’nın başlangıç noktası oldu. Büyük dil modelleriyle birlikte “kaybettiğin kişiyle konuş” iddiasındaki uygulamalar da çoğaldı.

    Not: Gerçek oldu. Teknik olarak dizideki sohbet aşaması bugün mümkün. Ama bölümün asıl sorduğu soru, yani bunun yas sürecine iyi mi geleceği yoksa onu uzatacağı mı, hâlâ cevapsız.

    2. Robot köpekler (“Metalhead”)

    Dizide: İnsanları durmaksızın takip eden dört bacaklı robotlar.

    Gerçekte: Dizinin yaratıcısı Charlie Brooker, bölümün Boston Dynamics’in robot köpeklerinden etkilendiğini söyledi. Aynı şirketin Spot adlı robotu bugün fabrikalarda, enerji tesislerinde ve tehlikeli alanlarda denetim için kullanılıyor. New York polisi 2020’de “Digidog” adını verdiği bir Spot kiraladı; ama robotun bir rehine olayında ve bir gözaltıda kullanılması büyük tepki çekti ve sözleşme Nisan 2021’de erken bitirildi.

    Not: Kısmen gerçek. Robot köpekler var ve gerçek işlerde kullanılıyor. Dizideki gibi kendi başına avlanan, silahlı bir robot ise yok. New York örneği, toplumun bu çizgiyi ne kadar hassas bulduğunu gösteriyor.

    3. Robot arılar (“Hated in the Nation”)

    Dizide: Arı nüfusu çöktüğü için tozlaşmayı yapan küçük dronlar.

    Gerçekte: Harvard’daki araştırmacılar yıllardır RoboBee adını verdikleri böcek boyutunda uçan robotlar üzerinde çalışıyor. 2018’de perakende devi Walmart’ın “insansız araçlarla tarım ürünlerini tozlaştırma” için patent başvurusu yaptığı ortaya çıktı.

    Not: Henüz değil. Patent başvurusu ve laboratuvar prototipleri var ama tarlada çalışan robot arı sürüleri yok. Gerçek arıların yaptığı işi bu ölçekte taklit etmek hâlâ çok zor.

    4. Her şeyi kaydeden gözler (“The Entire History of You”)

    Dizide: Kulağın arkasına takılan bir çip, yaşadığın her anı kaydediyor; istediğin anı geri sarıp tekrar izleyebiliyorsun.

    Gerçekte: Beyne takılan bir hafıza çipi yok. Ama kamera ve mikrofonlu akıllı gözlükler artık bir tüketici ürünü: gözlüğünle gördüğünü kaydedip paylaşabiliyorsun. Telefonundaki fotoğraf arşivi de yıllarını tarih ve yere göre geri sarmanı sağlıyor.

    Not: Kısmen gerçek. Kayıt kısmı büyük ölçüde var; vücuda yerleştirilmiş ve her şeyi sürekli kaydeden kısım değil. Bölümün uyardığı şey, yani her tartışmada “kayda bakalım” demenin ilişkilere etkisi, artık çok daha tanıdık geliyor.

    5. Puanlanan hayatlar (“Nosedive”)

    Dizide: Herkes karşılaştığı herkese 1’den 5’e kadar puan veriyor. Puanın düşükse ev kiralayamıyor, uçağa binemiyorsun.

    Gerçekte: Bu bölüm sık sık Çin’in sosyal kredi sistemiyle karşılaştırılıyor. Ama bu karşılaştırmanın abartılı olduğunu söyleyen pek çok analiz var: Gerçekteki sistem, dizideki gibi herkesin herkese puan verdiği tek bir uygulama değil; farklı kurumların ve şirketlerin kendi kayıtlarından oluşan, parçalı ve tartışmalı bir yapı. Öte yandan günlük hayatımızda puanlar her yerde: sürücüler yolcuya, ev sahipleri misafire, satıcılar alıcıya puan veriyor.

    Not: Kısmen gerçek. Tek bir süper puan yok; ama birbirine puan verdiğimiz düzinelerce küçük sistem var. Bölümün asıl eleştirdiği şey, puan için rol yapmak, belki de en gerçek olan kısmı.

    6. Bilinci dijital dünyaya taşımak (“San Junipero”)

    Dizide: İnsanların bilinci, ölümden sonra da yaşayabilecekleri bir sanal dünyaya aktarılıyor.

    Gerçekte: Sanal gerçeklik gözlükleri ve sanal dünyalar var. Ama bir insanın bilincini kopyalayıp bilgisayara aktarmak, bugünün bilimiyle mümkün değil; bilincin ne olduğunu bile tam olarak bilmiyoruz.

    Not: Henüz değil. Ve belki de hiç olmayacak. Ama bölüm teknolojiden çok bir aşk hikâyesi olduğu için bu, onu daha az etkileyici yapmıyor.

    Özet

    BölümTeknolojiDurum
    Be Right BackÖlen birini taklit eden sohbet botuGerçek oldu
    MetalheadRobot köpeklerKısmen gerçek
    The Entire History of YouHer şeyi kaydeden cihazKısmen gerçek
    NosediveHerkesin herkese puan verdiği dünyaKısmen gerçek
    Hated in the NationTozlaşma yapan robot arılarHenüz değil
    San JuniperoBilinci dijital dünyaya aktarmakHenüz değil

    Asıl mesele teknoloji değil

    Bu listeyi yaparken fark ettiğim şey şu oldu: Black Mirror’ın korkutucu tarafı hiçbir zaman teknolojinin kendisi değildi. Bir sohbet botu, bir robot ya da bir puanlama sistemi tek başına iyi ya da kötü değil. Dizinin asıl sorduğu şey, insanların bu araçlarla ne yaptığı. Teknolojiyi üreten taraftaysan bu soru daha da önemli hale geliyor: Bir ürünü yaparken sadece “yapabilir miyiz?” diye değil, “yapmalı mıyız?” diye de sormak gerekiyor.

    Benim yorumum

    Black Mirror’ı izlerken her bölümde hem şaşırıyorum hem de içimden “Ben de bu teknolojilerin bir parçası olayım” diyorum. Dizi ne kadar karanlık olursa olsun, ekranda gördüğüm her yeni fikir beni heyecanlandırıyor. Bu listeyi hazırlarken de bir kez daha seçtiğim meslekle gurur duydum: Bu teknolojileri izleyen değil, onları üreten tarafta olmak; üstelik yukarıdaki “yapmalı mıyız?” sorusunu da sorabilen biri olarak.

  • Netflix İzleme Geçmişi Panosu 2: Streamlit ile Panoya Dönüştürmek

    Netflix İzleme Geçmişi Panosu 2: Streamlit ile Panoya Dönüştürmek

    İlk bölümde Netflix izleme geçmişimi indirip temizledim ve not defterinde ona sorular sordum: En çok hangi diziyi izlemişim, hangi günler daha çok izliyorum, maraton günüm hangisi? Ama not defteri, cevabı görmek için her seferinde kod çalıştırmayı gerektiriyor. Bu bölümde aynı kodu, tıklayıp filtreleyebileceğin bir web panosuna çeviriyoruz. Hem de HTML ya da JavaScript bilmeden, sadece Python ile.

    Uygulamanın tüm kodu GitHub’da: pop-kultur-kodluyorum / netflix-pano.

    Streamlit nedir?

    Streamlit, Python koduyla web uygulaması yapmayı sağlayan açık kaynak bir kütüphane. Veri bilimcilerin en sevdiği araçlardan biri, çünkü mantığı çok basit: Bir Python dosyası yazıyorsun, st.title("Merhaba") dersen sayfada başlık, st.bar_chart(veri) dersen grafik çıkıyor. Biri bir düğmeye bastığında ya da bir filtreyi değiştirdiğinde Streamlit dosyayı yukarıdan aşağı yeniden çalıştırır ve sayfayı günceller.

    Bu “her etkileşimde yeniden çalıştır” fikri başta garip gelebilir, ama işi çok kolaylaştırıyor: Kodu not defterinde yazar gibi yukarıdan aşağı yazıyorsun, gerisini Streamlit hallediyor.

    Kurulum

    Streamlit kendi bilgisayarında çalışır (Colab’da doğrudan çalışmaz). Terminalde:

    pip install streamlit pandas altair

    Kurulumu denemek için streamlit hello yazabilirsin; tarayıcında bir örnek uygulama açılır.

    Uygulamanın parçaları

    Uygulama tek bir dosya: app.py. Altı bölümden oluşuyor. Tamamı GitHub’da; burada her bölümün önemli satırlarını anlatıyorum.

    1. Temizleme fonksiyonları: ilk bölümden aynen

    Tarihleri çözen tarihi_coz ve diziyi filmden ayıran ayir fonksiyonlarını ilk bölümden hiç değiştirmeden taşıdım. Hepsini tek bir fonksiyonda topladım:

    @st.cache_data
    def veriyi_hazirla(ham):
    df = ham.rename(columns={"Title": "baslik", "Date": "tarih"})
    df["tarih"] = tarihi_coz(df["tarih"])
    df = df.dropna(subset=["tarih"])
    df[["isim", "tur"]] = df["baslik"].apply(lambda b: pd.Series(ayir(b)))
    # ... ikinci adım: tekrar eden ön ekleri dizi say
    return df

    @st.cache_data satırı bir dekoratör: fonksiyonun üstüne yapışan bir etiket gibi düşün. Streamlit’e “bu fonksiyonu aynı veriyle tekrar çağırırlarsa baştan hesaplama, önceki sonucu ver” diyor. Her filtre değişikliğinde dosya yeniden çalıştığı için bu önemli; yoksa binlerce satırı her tıklamada yeniden temizlerdik.

    2. Dosyayı almak

    dosya = st.file_uploader("NetflixViewingHistory.csv dosyanı yükle", type="csv")
    if dosya is None:
    st.info("Henüz dosya yüklemedin. Aşağıda hayali bir örnek veriyle gösteriyorum.")
    df = veriyi_hazirla(ornek_veri())
    else:
    df = veriyi_hazirla(pd.read_csv(dosya))

    st.file_uploader sayfaya bir dosya yükleme kutusu koyar. Kullanıcı henüz dosya seçmediyse None döner; o zaman pano boş kalmasın diye hayali bir örnek veri gösteriyoruz. Bu örnek veri tamamen uydurma dizi isimlerinden oluşuyor.

    3. Filtreler: kenar çubuğu

    with st.sidebar:
    yillar = sorted(df["tarih"].dt.year.unique())
    secilen_yillar = st.multiselect("Yıl", yillar, default=yillar)
    tur = st.radio("Tür", ["Hepsi", "Dizi", "Film"], horizontal=True)
    f = df[df["tarih"].dt.year.isin(secilen_yillar)]
    if tur != "Hepsi":
    f = f[f["tur"] == tur]

    with st.sidebar: bloğunun içine yazılan her şey sol taraftaki kenar çubuğuna gider. st.multiselect birden fazla yıl seçmeye, st.radio türlerden birini seçmeye yarıyor. Seçimler sıradan Python değişkenlerine düşüyor; sonra pandas ile tabloyu filtreliyoruz. Sayfanın geri kalanı hep bu filtrelenmiş f tablosunu kullanıyor, böylece bir filtre değişince tüm pano birlikte değişiyor.

    4. Özet kartları

    k1, k2, k3, k4 = st.columns(4)
    k1.metric("Toplam kayıt", len(f))
    k2.metric("Farklı dizi", f.loc[f["tur"] == "Dizi", "isim"].nunique())
    k3.metric("Film", int((f["tur"] == "Film").sum()))
    k4.metric("Maraton günü", f"{gunluk.max()} kayıt")

    st.columns(4) sayfayı dört eşit sütuna böler, metric da her sütuna büyük bir sayı koyar. Panonun en üstündeki özet buradan geliyor.

    5. Grafikler

    Streamlit’in kendi st.bar_chart fonksiyonu hızlı ama günlerin sırasını alfabetik yapıyor (Cuma, Cumartesi, Çarşamba…). Haftanın günlerini doğru sırada göstermek ve renkleri seçmek için Streamlit’le birlikte gelen Altair kütüphanesini kullandım. Aynı çubuk grafiği üç yerde kullanacağım için küçük bir fonksiyon yazdım:

    def cubuk(veri, x, y, renk=BOGURTLEN, sira=None, x_baslik="", y_baslik="Kayıt"):
    return (
    alt.Chart(veri)
    .mark_bar(color=renk, cornerRadiusEnd=4)
    .encode(
    x=alt.X(x, sort=sira, title=x_baslik),
    y=alt.Y(y, title=y_baslik),
    tooltip=[x, y],
    )
    )

    sort=sira parametresine ["Pazartesi", "Salı", ...] listesini verince günler doğru sıraya diziliyor. tooltip da fareyle çubuğun üzerine gelince sayıyı gösteriyor. Grafiği sayfaya koymak için st.altair_chart(grafik) yeterli. (GitHub’daki tam sürümde eksen biçimleri için birkaç ayar daha var.)

    En çok izlenen 10 dizi ise grafik değil tablo: st.dataframe(ilk10, hide_index=True). Uzun dizi isimleri tabloda daha rahat okunuyor.

    6. Bir diziye yakından bak

    diziler = f.loc[f["tur"] == "Dizi", "isim"].value_counts().index.tolist()
    secilen = st.selectbox("Dizi seç", diziler)
    d = f[f["isim"] == secilen]

    st.selectbox bir açılır menü koyar. Liste en çok izlenenden en aza doğru sıralı. Bir dizi seçince ilk ve son izleme tarihini ve o dizinin aylara göre grafiğini gösteriyoruz. Bir diziyi birkaç haftada bitirip bitirmediğini ya da yıllara yayıp yaymadığını bu grafikte görebiliyorsun.

    Çalıştırmak

    1. GitHub’dan netflix-pano klasörünü indir (ya da depoyu klonla).
    2. Terminalde o klasöre gir ve pip install -r requirements.txt yaz.
    3. streamlit run app.py yaz. Tarayıcında pano açılır.
    4. Netflix’ten indirdiğin NetflixViewingHistory.csv dosyasını yükleme kutusuna sürükle.

    Dosyayı Netflix’ten nasıl indireceğini ilk bölümde adım adım anlattım.

    Panoyu internete koymak

    Panoyu arkadaşlarınla paylaşmak istersen Streamlit Community Cloud’u kullanabilirsin: GitHub hesabınla giriş yapıp deponu ve app.py dosyasını seçiyorsun, uygulama birkaç dakika içinde bir web adresinde yayına giriyor. Uygulama kimsenin verisini kendi içinde taşımıyor; her ziyaretçi kendi dosyasını yüklüyor.

    Gizlilik notu: Uygulama yüklenen dosyayı hiçbir yere kaydetmiyor, sadece açık olan oturumda işliyor. Yine de ham CSV dosyanı GitHub gibi herkese açık bir yere koyma. İzleme geçmişi, ne zaman uyanık olduğuna kadar çok şey anlatır. Paylaşırken sadece toplamları ve grafikleri paylaş; ben de bu yazıda öyle yaptım.

    Panoda ne gördüm?

    Kendi verimi yükleyince pano şunları gösterdi:

    • Ağustos 2019’dan bu yana toplam 4.986 kayıt, 487 farklı dizi ve 350 film.
    • Haftanın en çok izlediğim günü Pazar, ikinci sırada Pazartesi. Hafta içinin diğer günleri birbirine çok yakın.
    • Maraton günümde 36 kayıt var.

    Kendin dene

    • Kenar çubuğuna bir saat filtresi ekleyemezsin, çünkü Netflix dosyasında saat yok. Ama bir ay filtresi ekleyebilirsin: st.slider ile 1-12 arası seçim yap.
    • “En çok izlenen 10 dizi” yerine kullanıcının kaç dizi görmek istediğini seçmesini sağla: st.number_input("Kaç dizi?", 5, 30, 10).
    • Bir arkadaşınla karşılaştır: İki dosya yükletip iki kişinin haftalık çubuklarını yan yana göster.

    Bir sonraki pop kültür projesinde Netflix verisini bir adım daha ileri taşıyıp basit bir öneri sistemi yazacağız: “Netflix’te Ne İzlesem?”