11 Nisan 2008

Machine Learning

Machine Learning (Makine Öğrenimi) yapay zekanın bir alt sınıfıdır. Machine Learning, bilgisayarların belirli bir algoritma ve teknikler ile birşeyler "öğrenebilme"lerini sağlar. Machine Learning ile genelde Data Mining (Veri Toplama) yapılır. Genel olarak 2 tür machine learning vardır; inductive ve deductive. Inductive belirli şablonlar kullanarak veri öğrenimini sağlar. Bu yazıda size Inductive yolunu bir örnek ile açıklamaya çalışacağım.

Şablon bizim için anahtar kelimedir. Belirli şablonlar üzerine kurulu bir sistemde, istediğiniz verileri alabilirsiniz. Şablonlar'ın bu kadar önemli olduğu bir yapı için programlama dili olarak; Regular Expressions (Düzenli İfadeler)'ı en iyi şekilde kullanabileceğimiz Perl'i seçtim. "get" fonksiyonu için LWP::Simple kullanılmıştır. Yazı içerisinde yazılan programın tamamını, yazının en altında bulabilirsiniz.

divxplanet.com üzerinde altyazısı bulunan filmleri ve dizileri nasıl alabileceğimize dair bir örnek ele alalım.

Hemen siteye bir göz gezdirelim. Sitede film listeleri belli bir şablon üzerine kurulu. Şablon bizim için anahtar kelime idi. 0-9 ile başlayan film listesine bakalım: [1]. Bu 0-9 ya da herhangi bir harf için standart bir film listeleme sayfasıdır. Film adları zaten bizim almak istediğimiz veri. Hemen sayfa içerisindeki değişkenlere bakalım. Tüm filmler baş harfine ve sayfalara göre sayfalara bölünmüş durumda. Öncelikle her harf için sayfaları almalı ve daha sonra harfin film listelerinin kaç sayfadan oluştuğunu öğrenmeliyiz. Bu sayede tüm sayfalara girebilir ve istediğimiz verileri elde edebiliriz.

Tekrar hatırlatayım şablon bizim için anahtar kelime idi. Hemen şablon arayalım. İlk önce her harfin sayfasını alacaktık. Bir harf için listelenen filmlerin URL'lerine bakıyoruz:

http://www.divxplanet.com/sub/b/0-9/1.html
http://www.divxplanet.com/sub/b/A/1.html
http://www.divxplanet.com/sub/b/B/1.html
...

Gördüğünüz gibi burada bir şablon söz konusu. URL de yer alan harf ve arkasından gelen sayı sayfa numarasını oluşturuyor. Tüm harfleri alacağımız için bir array oluşturuyoruz ve bu harfleri içine koyuyoruz:


my @harfler = qw (0-9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z);


Tüm harfleri alıp üzerinde işlem yapacağız. Her bir harfin içeriğini get ile alacağız. Arrayımızın her üyesi için işlem yapacağımızdan foreach ile devam ediyoruz.


foreach my $harf (@harfler)
{
my $icerik = get ("http://www.divxplanet.com/sub/b/$harf/1.html");


Döngümüz her harfi alacak. Şimdi işin Machine Learning kısmına geçiyoruz. İlk önce aldığımız içeriğin kac sayfadan oluştuğunu öğrenmeliyiz ki her harfin her sayfasına girebilelim ve her film adını alabilelim.

Sayfanın kaynak kodlarına bakıp "Sayfalar" için bir şablon arayacağız. Sayfalar:

<tr><td><br><br><center>Sayfa<br><img src="/images/geri.gif" border="0"> | 1 <a href=/sub/b/A/2.html>2</a> <a href=/sub/b/A/3.html>3</a> <a href=/sub/b/A/4.html>4</a> <a href=/sub/b/A/5.html>5</a> <a href=/sub/b/A/6.html>6</a> <a href=/sub/b/A/7.html>7</a> <a href=/sub/b/A/8.html>8</a> <a href=/sub/b/A/9.html>9</a> <a href=/sub/b/A/10.html>10</a> <a href=/sub/b/A/11.html>11</a> <a href=/sub/b/A/12.html>12</a> <a href=/sub/b/A/13.html>13</a> <a href=/sub/b/A/14.html>14</a> <a href=/sub/b/A/15.html>15</a> <a href=/sub/b/A/16.html>16</a> <a href=/sub/b/A/17.html>17</a> <a href=/sub/b/A/18.html>18</a> <a href=/sub/b/A/19.html>19</a> <a href=/sub/b/A/20.html>20</a> <a href=/sub/b/A/21.html>21</a> <a href=/sub/b/A/22.html>22</a> <a href=/sub/b/A/23.html>23</a> <a href=/sub/b/A/24.html>24</a> | <a href="/sub/b/A/2.html"><img src="/images/ileri.gif" border="0"></a></center><br><br></td></tr></table>

Kodları içerisinde yer alıyor. Bizim burdaki sayfa sayılarını alabilmemiz için önce bu bölümü almalıyız. Basit bir regex ile bu kısmı alıyoruz ve bunu $sayfalar değişkenine atıyoruz:

my ($sayfalar) = $icerik =~ /<tr><td><br><br><center>Sayfa<br>(.*?)<\/table>/;

Sayfalarımızda sadece rakamlara ulaşmalıyız. Tüm gereksiz karakterleri temizliyoruz. $sayfalar 'ın içeriği html kodları ve | karakterinden oluşmakta. Onları $sayfalar değişkeninden ayıklıyoruz:

$sayfalar =~ s/<.*?>|\||//g;

Şimdi sayfalar değişkeni: "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24" değerini aldı. Sadece aralarında boşluk oluşan sayılar. Şablonumuz belli oldu. Her sayı ile işlem yapacağımız için sayıları boşluk karakterinden ayırarak bir array a atıyoruz:

my @sayfalar = split (" ", $sayfalar);

@sayfalar arrayının uzunluğu bize sayfa sayısını veriyor. Böylece programımız bir harf içinde bulunan sayfa sayısını öğrenmiş oldu.

Şimdi her sayfa içerisinde bulunan filmleri alabileceğiz. Bunun için her harfin her sayfasına girmemiz gerekli. Yine arrayımızın her elemanını kullanacağımızdan foreach döngüsünü kullanıyoruz:

foreach my $sayfa (@sayfalar)
{

Linkimizi tekrar hatırlayacak olursak: [2] artık sayfa değişkenini de elde ettik. Şimdi programımız her sayfayı çağıracak. Yine get fonksiyonu ile sayfa içeriğini alıyoruz ve bunu yeni local $icerik değişkenimize atıyoruz:

my $icerik = get ("http://www.divxplanet.com/sub/b/$harf/$sayfa.html");

Filmleri alabilmemiz için yine sayfanın kaynak kodlarını açıyoruz ve şablon arıyoruz. Site içerisinde filmler:

<tr><td> » <a href="/sub/m/11976/A-ay.html" title="A ay">A ay</a> (1988)</td></tr>

Kodları arasında yer alıyor. Tüm filmler aynı şekilde listelendiğinden buda bize şablonumuzu veriyor. Yine regex'e baş vurarak filmleri bir @filmler arrayına atıyoruz:

my (@filmler) = $icerik =~ /<tr><td>.*?<a href="\/sub\/m\/[\d]+\/.*?.html" title="(.*?)">.*?<\/a> \([\d]+\)<\/td><\/tr>/g;

Biraz karışık gibi gelse de düzenli ifadeleri bilen biri için yine basit bir regex kullandık. Şimdi filmlerin adlarını yazdırmaya geldi sıra:

print "$_\n" foreach (@filmler);

Programımız içerisinde açtığımız braketlerimizi kapatarak programımız tamamlıyoruz.

}
}

Ve programımız bitti. Gördüğünüz gibi çok basit bir işlem ile divxplanet üzerinde bulunan tüm sayfaları aldık. Programımız bir harf için bulunan sayfa sayısını öğrendi ve bize her sayfada bulunan filmlerin adlarını listelemeyi başardı. Data Mining'in temeli budur. Makine şablon üzerindeki değişkenleri öğrenir ve bunları kullanarak verilere ulaşabilir. Bunu, herhangi bir şablon üzerine kurulu bir sistemde uygulayabilirsiniz.

Yukarıda yazılan programın tamamı:

#!/usr/bin/perl
use LWP::Simple;
my @harfler = qw (0-9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z);
foreach my $harf (@harfler)
{
my $icerik = get ("http://www.divxplanet.com/sub/b/$harf/1.html");
my ($sayfalar) = $icerik =~ /<tr><td><br><br><center>Sayfa<br>(.*?)<\/table>/;
$sayfalar =~ s/<.*?>|\||//g;
my @sayfalar = split (" ", $sayfalar);
foreach my $sayfa (@sayfalar)
{
my $icerik = get ("http://www.divxplanet.com/sub/b/$harf/$sayfa.html");
my (@filmler) = $icerik =~ /<tr><td>.*?<a href="\/sub\/m\/[\d]+\/.*?.html" title="(.*?)">.*?<\/a> \([\d]+\)<\/td><\/tr>/g;
print "$_\n" foreach (@filmler);
}
}


Notlar:
Machine Learning ve Data Mining kavramlarının Türkçe karşılıklarını kafadan uydurdum.

Copyright (C) 2008 Onur Aslan <onuraslan@users.sourceforge.net>
Metin GNU Özgür Belgeleme Lisansı kapsamındadır.

0 yorum: