K-Means

Dün biri bana "şirkette yazdığım en karmaşık algoritma k-means yea" diye hava attı. Düşündüm de şimdiki işimde kullandığım en karmaşık algoritma DFS. O da abuk subuk bir yerde. Altta kalmamak için ben de k-means yazayım neyim eksik dedim :) .

K-means bir çeşit sıkıştırma algoritması olarak da kullanılabiliyor, Bishop'un kitabında örneği de var. Eğer bir resmi k-means ile sıkıştırmak istiyorsak standart k-means'i pikseller üzerinde tek boyutta uygulayabiliriz. Yanlış hatırlamıyorsam Bishop kitabında her bit için uyguluyordu, sadece 3 renk için uygulamak daha kolayıma geldi :) .

Elimizdeki resim şu olsun (kaynak);

ironman

K=2 ile sıkıştırdığımızda elimizdeki resim aşağıdaki gibi olacak;

ironman_k_2

K arttıkça resmin orijinale yaklaşmasını bekliyoruz. K=5 ile sıkıştırdığımızdaysa resim aşağıdaki gibi olacak;

ironman_k_5

Ben kendime C#'ta k-means yazmadı dedirtmem! :) (Bu arada cidden Python'daki list comprehension'lar hayat kurtarıyormuş, bir kez daha anlamış oldum).

OracleCommand.BindByName

Diyelim ki C# ile, Oracle veritabanında bulunan aşağıdaki stored procedure'u çalıştırmak istiyoruz.

Yazmamız gereken kod aşağıdaki gibi bir şey olacak;

Burada parametreleri eklerken SP ile aynı sırada verdiğimiz için bir sıkıntı yok ama kodu aşağıdaki gibi yazsaydık SP içerisinde PARAM1  2, PARAM2  ise 1 değerini alacaktı.

Oracle.DataAccess dll'indeki OracleCommand  sınıfı, aksi belirtilmediği sürece parametrelerin isimlerini değil verilme sıralarını dikkate alıyor. Neden default olarak böyle olduğunu anlamadığım bir şekilde bu durum, command  nesnesindeki BindByName  parametresi ile çözülebiliyor.

İşin gücün insana sıkıntı çıkarmak Oracle.

Listenin transpozunu almak

Grid gibi, aynı tipten verinin çok fazla sekilde tekrarlandıgı durumlarda, serialization esnasında yazılan metadata yükünden dolayı veriyi taşımak problem olabiliyor.

Misal aşağıdaki gibi bir Row sınıfının olduğunu düşünün;

Sadece Row sınıfı elemanlarından oluşan bir listeyi JSON'a çevirip göndermeye çalıştığımızda elimizdeki mesaj aşağıdaki gibi bir standart JSON mesajı olacak.

Eğer dediğim gibi, göstereceğimiz veri standart bir Row listesiyse, yani Row sınıfından türeyen herhangi bir sınıfın nesnesini barındırmıyorsa, mesaj içinde sürekli tekrarlanan alan adlarından kurtulmak için listenin transpozunu alabiliriz.

Listenin transpozunu almanın lineer cebirde matrisler üzerinde uygulanan transpoz işleminden bir farkı yok aslında. Örneğin nasıl ki

\[M = \begin{pmatrix}1 & 2 \\ 3 & 4\end{pmatrix}\]

şeklindeki bir matrisin transpozu

\[M^T = \begin{pmatrix}1 & 3 \\ 2 & 4\end{pmatrix}\]

ise, yani satırlarla sütunlar yer değiştiriyorsa liste üzerinde de aynı işlemi yapacağız.

Obje Col1 Col2 Col3 Col4 Col5
Obj1 Column1 Column2 Column3 0 0
Obj2 Column1 Column2 Column3 1 3.1415926535897931

şeklindeki bir obje listesinin transpozu

Obj1 Obj2
Col1 Column1 Column1
Col2 Column2 Column2
Col3 Column3 Column3
Col4 0 1
Col5 0 3.1415926535897931

olacak. Böylece artık her satırda nesne yerine primitif listesi gönderebiliriz.

Aşağıdaki kod basit bir şekilde bu işlemi yapıyor.

Artık göndereceğimiz veri aşağıdaki gibi

Böylece, eleman sayılarına göre mesaj boyutlarındaki değişim aşağıdaki gibi olacak.

Eleman Sayısı Normal(byte) Transpoz(byte)
2 162 133
1000 89674 52719
10000 906712 536757
100000 9167843 5467888

Dolu tabloların iletiminde bu yöntem etkin bir çözüm sağlıyor. Boşa yakın (sparse) tablolarda ya da değişik obje tipleri içeren durumlarda ise çok fazla bir yarar sağlamayacaktır.