Bir Makalenin Özgün Bir Makale Olup Olmadığını Anlamak İçin Bir Yöntem
Web sitenize yüklenen bir makalenin özgün olup olmadığını, ya da sizin sitenizdeki makaleleri aşıranların kimler olduğunu otomatik olarak saptamanın bir yolu var.
Vektör Uzayı Modeli denen yöntemle makalelerin birbirlerine benzerliklerini karşılaştırabilirsiniz.
Bu yöntem şu şekilde kullanılıyor:
Önce makalelerin farklılıklarını temsil edebilecek bir sözcük listesi oluşturuyoruz. Bu liste, bir makalede sık geçen ama makaleler arasında az geçen sözcüklerden seçilerek oluşturuluyor. Sonra bu listeyi bir dizine alıyoruz, ve listedeki her bir sözcüğü sanki çok boyutlu bir vektörün değişkeni imişçesine işliyoruz. Bir makaledeki bu listede olan sözcüklerin görülme sıklıklarının 0-1 normalizasyonu bizim vektörümüzün katsayıları olacak.
Örneğin listemizde "fizik" sözcüğü varsa, ve 321 sözcüklük bir makalede 12 kez "fizik" geçiyorsa katsayımız: 12/321=0.0373831 olacak. Elimizdeki her makale için oluşturduğumuz listede bulunan sözcükler varsa bu katsayıları hesaplayıp bir dizine alıyoruz. Bu bizim çok boyutlu vektörümüz.
Malum, vektörler yön gösterir. Ok şekliyle ifade ederiz fizikte, matematikte zaten. İşte bu vektörleri elde ettikten sonra aynı yönü işaret edip etmediklerine bakıyoruz, aynı yöne doğru bakan vektörlerin temsil ettikleri makaleler benzerdir. Benzerlik oranı, iki vektörün arasındaki açıyla orantılı.
İki vektör arasındaki açıyı ise bu iki vektörün nokta çarpımını, vektörlerin determinantlarının çarpımına bölerek bulabiliriz. Bu bölüm bize açının kosinüsünü verecektir. Yani tam olarak aynı noktaya bakıyorlarsa 1, ortogonallerse, dik açı yapıyorlarsa 0 değerini alacağız.
Matematik ifadesi:
cos(açı) = vektör1 . vektör2 / (det(vektör1)*det(vektör2))
Örneğin vektör1, özgün olup olmadığını merak ettiğimiz makalenin vektörü olsun, vektör2'ler de sırayla daha önce web sitemize yüklenmiş makalelerin vektörleri olsun tek tek.
Ya da vektör1 sizin rakibiniz bir web sitesine yeni yüklenmiş bir makalenin vektörü, vektör2'ler de sırayla sizin sitenizdeki makalelerin vektörleri olabilir. Böylece rakip site sizden makale aşırdıysa bunu hemen anlayabilirsiniz.
Yapması anlatmasından daha kolay. Örnekliyorum:
Örnek bir sözcük listemiz olsun bu aşağıdaki, yalnzıca 8 sözcük olduğundan 8 boyutlu bir uzaydaki bir vektör bu. Sizinse sağlıklı bir makale ayırdetme için 1000 boyutlu bir uzayda çalışmaya, ve uygun ayırtedici bir sözcük listesine ihtiyacınız olacak:
$eslenik=array(
'bir',
've',
'ekran',
'Windows',
'bu',
'Samsung',
'olarak',
'Mobile'
);
Şimdi vektörleri tutacak bir SQL tablosu hazırlayalım. 8 tane için hadi neyse de 1000 tane için bir tabloyu elle yazmak akılcıl değil, bizim yerimize bir program yazsın:
<?php
$adet=8;
echo "
USE vektoruzayideneme;
#drop table vsmvektor;
CREATE TABLE `vsmvektor` (
`no` int(11) unsigned NOT NULL auto_increment,
`zaman` timestamp(14) NOT NULL default '',
`durum` tinyint unsigned NOT NULL default 0,
";
for($i=0;$i<$adet;$i++) {
$j=$i;
if ( $i < 1000 ) $j="0".$i;
if ( $i < 100 ) $j="00".$i;
if ( $i < 10 ) $j="000".$i;
echo " `k".$j."` float NOT NULL default 0,\n";
}
echo " PRIMARY KEY `no` (`no`),
KEY `zaman` (`zaman`),
KEY `durum` (`durum`)
) TYPE=MyISAM;
";
?>
bunu deneme.php diye kaydedip, çalıştırıp çıktısını bir yere yazıp mysql'e verelim:
#php deneme.php > vektorler.sql
#mysql < vektorler.sql
Bu "vsmvektor" adlı bir veritabanı tablosu oluşturttu bize.
Devam edelim, ve bir yazının vektörünü hesaplayan işlevi yazalım:
function f_vsmvektorbul($eslenik,$yazi) {
$vektor=array();
$sayac=array();
$say=0;
$esadet=count($eslenik);
$dyazi=str_replace("\r"," ",$yazi);
$dyazi=str_replace("\n"," ",$dyazi);
$dyazi=str_replace("\t"," ",$dyazi);
$dyazi=preg_replace("/([[:punct:][:digit:] ]+)/"," ",$dyazi);
$dyazi=trim($dyazi);
$metin=explode(" ",$dyazi);
$ydizi=array_count_values($metin);
$adet=count($metin);
for($j=0;$j<$esadet;$j++) {
if ( $ydizi[$eslenik[$j]] == "" ) {
$tane=0;
} else {
$tane=$ydizi[$eslenik[$j]];
}
$vektor[$j]=$tane/$adet;
} // for j
return $vektor;
}
?>
Burada $eslenik dizisi (array) işte o bizim çıkardığımı özel sözcük listesi. $yazi ise çok boyutlu vektörü bulunacak düz yazı biçiminde makale. İşlevin yaptığı ise basit, sözcükleri sayıyor yüzdesini bulup 0-1 normalizasyonlu olarak bir vektör (bu durumda bir array/dizi) döndürüyor.
Bu vektörleri hesapladıkça veritabanına sokacağımız bir işlev daha yazalım:
function f_vsmvektorsok($vektor) {
$maks=8;
$adet=count($vektor);
if ( $adet > $maks ) $adet=$maks;
$komut="INSERT INTO vsmvektor (";
for($i=0;$i<$adet;$i++) {
$j=$i;
if ( $i < 1000 ) $j="0".$i;
if ( $i < 100 ) $j="00".$i;
if ( $i < 10 ) $j="000".$i;
$komut.="k".$j.",";
}
$komut.="zaman) VALUES (";
for($i=0;$i<$adet;$i++) {
$komut.=$vektor[$i].",";
}
$komut.="NOW());";
mysql_query($komut);
$no=mysql_insert_id();
return $no;
}
İşlevin içine $maks değişkeni ile sözcük listemizin uzunluğunu (vektör uzayımızın boyutuna denk) belirtmeyi unutmuyoruz. Bu örnek için 8. İşlevin yaptığı ise o uzun mysql komutunu oluşturmak, bununla vektör katsayılarınaı veritabanına sokmak ve bize nereye soktuğu bilgisini döndürmek. Bu vektör numarasını programınızda ilgili makalenin numarası ile eşleştirmeyi unutmamalısınız. Bu ayrıntıları yazı uzamasın diye yazmıyorum çünkü.
Pratik örneklerle devam edelim:
İki vektör arasındaki açıyı hesaplayalım:
function f_vsmacisi($vek1,$vek2) {
$tane=count($vek1);
$noktacarpimi=0;
for ($i=0;$i<$tane;$i++) $noktacarpimi=$noktacarpimi+$vek1[$i]*$vek2[$i];
$det1=0;
for ($i=0;$i<$tane;$i++) $det1=$det1+$vek1[$i]*$vek1[$i];
$det1=sqrt($det1);
$det2=0;
for ($i=0;$i<$tane;$i++) $det2=$det2+$vek2[$i]*$vek2[$i];
$det2=sqrt($det2);
$costheta=0;
if ( $det1 != 0 && $det2 != 0 ) {
$costheta=$noktacarpimi/($det1*$det2);
}
$costheta=log10(1+$costheta*9);
return $costheta;
} // func. f_vektoracisi
Yukarıda verdiğim matematik formulüne bir ek yaptım bu örnekte. Dikkat ederseniz cos(açı) yerine 10 tabanında logaritmasını döndürüyorum. Bu, eğer az sözcükle çalışıyorsanız, vektör arasındaki farklılıkları sivriltmeye yarıyor. Log10(1) 0 değerini verir, log10(10) da 1. Ama logaritma sayesinde 1'e yakın olanlar daha yaklaşır, 0'a yakın olanlar da 1'den daha uzaklaşır. Birbirine benzese de az benzeyen makaleleri daha kolay ayırt edebiliriz böylece.
Kullanımı ise şöyle:
$makale1=file_get_contents("http://birsiteninbirmakalesi.html");
$makale1=trim(preg_replace("/( +)/"," ",preg_replace("/<(.*)>/U"," ",$makale1)));
$makale2=file_get_contents("birbaşka.html");
$makale2=trim(preg_replace("/( +)/"," ",preg_replace("/<(.*)>/U"," ",$makale1)));
// veya $makale2=file_get_contents("birbaşka.txt");
// kısaca düz yazı olacak bunlar.
// Ayrıca UTF-8 ve ISO-8859-9 farklılıklarını ve diğer ayrıntıları unutmamalı,
// ilgili dönüşümleri ayrıca yapmalısınız.
$vektor1=f_vsmvektorbul($eslenik,$makale1);
$vektor2=f_vsmvektorbul($eslenik,$makale2);
$benzerlik=f_vsmacisi($vektor1,$vektor2);
if ( $benzerlik > 0.95 ) echo "Vay uyanık, bu makaleler hık demiş burunlarından düşmüş.";
Bunun bir kullanımı daha var. Eğer sitenizdeki her makalenin vektörlerini sql'de depolar, ve yeni bir tablo daha oluşturup buna da her makale çiftinin birbirleri ile olan açılarını kaydederseniz birbiri ile ilgili makaleleri bulabilirsiniz. Tek yapmanız gereken o an gösterilmekte olan makalenin bu tablodaki açılarıdan, mesela 0.5'ten daha büyük olduğu diğer vektörleri sql ile sorgulatmak ve denk gelen makaleleri çekip önermek: "Bu makaleler de ilginizi çekebilir" şeklinde.
Ya da otomatik kategorilendirme uygulamaları, veya başka türlü semantik kullanım uygulamaları da yapabilirsiniz.
Kolay gelsin.
İlker Fıçıcılar
4 Haziran 2010
İlgili Benzer Yazılar:
Arama önerileri:
HTML,
HTML kodları,
PHP,
web ontolojisi,
makale,
makaleler,
web tasarımı,
web sayfası hazırlama,
web tasarım kodları,
semantik web,
web 3.0,
vektör uzayı modeli,
vector space model,
makale gruplama,
otomatik kategorilendirme,
vektör modeli,
Kaynak gösterecekler için referans:
"Bir Makalenin Özgün Bir Makale Olup Olmadığını Anlamak İçin Bir Yöntem",
İlker Fıçıcılar,
http://www.KlavyeMonitor.com/Bir_Makalenin_Ozgun_Bir_Makale_Olup_Olmadigini_Anlamak_Icin_Bir_Yontem.html
, Haziran 2010
|