05 AĞUSTOS 2017
CUMARTESİ
15.46
Youtube
Youtube kanalım açıldı! Daha detaylı ve güncel konu anlatımları için takip etmeyi unutmayın.
Metin Madenciliği (Text Mining) - Yazar Tespit Uygulaması Örneği

Metin madenciliği, veri madenciliğinin bir alt başlığı olarakta bilinebilir. Bu kavram hakkında bir geniş örnek ile daha fazla bilgi sahibi olacağız.

 

Metin madenciliği, temelde elde kayıtlı olan birbirinden farklı metinlerin analizleri ve bunların sonuçlarına göre alınabilecek tahmini sonuçları kapsamaktadır. Bir anlamda bizim yapacağımız çıkarımlar bir kenara, makinenin bizim yerimize yapacağı çıkarımlar ve sonuçların daha doğru olabileceğinin göstergesidir.

Metin madenciliğinde metinler veri kabul edilir. Elde bulunan her metin bir veri gibi işlenir ve bir çıkarım yapılır.

Metin madenciliğine en büyük örneklerden birini PHP yardımı ile yazalım ve sonucu inceleyelim;

Öncelikle olayı bir anlatalım. Örneğimiz bir yazar tespit uygulaması.

Yazar Tespit Uygulaması Nedir?

Elimizde yazarlara ait birbirinden farklı makaleler olduğunu düşünelim. Bu yazar ve makaleleri bilgisayarımızda .txt dosyalarında saklanıyor olsun. Biz yeni gelen bir makalenin hangi yazara ait olacağını tahmin etmeye çalışıyoruz. Yani;

Böyle bir dosya sistemine sahibiz. Bu dosya sistemimizde farkettiğiniz üzere 4 farklı yazarımız ve bu yazarlara ait 5 farklı makaleleri bulunuyor. Bizim amacımız ise tam olarak şu;

Yani bizim elimizde yeni bir makale var (her yazara ait 5 makaleden farklı olarak) ve biz bu makaleyi hangi yazarımızın yazmış olabileceğini tahmin etmeye çalışıyoruz.

Nasıl Bir Yol İzleyeceğiz?

Aşağıdaki gif olayın nasıl işlediğini özetlemektedir.

Gif'te görüntülenen 3 farklı yazara ait verilerdir. Bu veriler temelde gösterildiği gibi ana dosya ile karşılaştırılıyor.

  1. Tüm yazarların eski makaleleri incelenir ve en çok kullandıkları kelimeler tespit edilir.
  2. Taranan makale içindeki metin de tüm kelimelerine ayrılır ve yazarın en çok kullandığı kelimeler ile karşılaştırılır.
  3. Yazar örneğin SPOR kelimesini normal makalelerinde 15 kez kullanmış olsun. O zaman taranan makalede eğer spor geçerse o yazara 15 puan verilir.
  4. Verilen puanlar yüzdelik dilimlere ayrılır ve yüzdesi en yüksek kişi makaleyi yazan kişi olabilir.

Şimdi bunu kod olarak inceleyelim.

Kodları 4 başlıkta inceleyeceğiz.

1. Aranan Makale

Dosya yapımızı zaten üstte gördük. Bu yapıya uygun bir şekilde kodları takip edebiliriz.

$arananYazarKim = array();
$aranan = fopen('aranan.txt', 'r');
$icerik = fread($aranan, filesize('aranan.txt'));

	$kelimeTespiti = explode(" ", $icerik);

	$cokKullanilanKelimeler = array_count_values($kelimeTespiti);
	arsort($cokKullanilanKelimeler);
	$a = 0;

	foreach($cokKullanilanKelimeler as $kullanilan => $kez) {
	    array_push($arananYazarKim, $kez."@@@".$kullanilan);
	    $a++;
	    if($a == 1000) {break;}
	}

fclose($aranan);

Üstteki kodda öne çıkan kısımlara göz atalım;

  • fopen, fread ve fclose komutları "aranan.txt" dosyamızı açmak ve okumak için kullanmış olduğumuz komutlar.
  • $kelimeTespiti adındaki değişkenimiz makaleyi boşluklardan ayırarak kelimelere ulaşmaktadır.
  • array_count_values() fonksiyonumuz ile hangi kelimenin kaç kez tekrarlandığını buluyoruz. 
  • arsort() fonksiyonumuz ise büyükten küçüğe, yani çok kullanılan kelimeden az kullanılan kelimeye göre bir sıralama yapmaktadır.
  • array_push() fonksiyonumuz ile foreach içerisinde $arananYazarKim adındaki dizimize kelime ve kelimenin kaç kez kullanıldığını şöyle gönderiyoruz: 15@@@SPOR
  • Gördüğümüz $a değişkeni ise tamamıyla size bırakılmış. Burada 1000 değeri en çok kullanılan 1000 kelimeye kadar dizmeye yarıyor. Bu hiç katmayabiliriz.

2. Tüm Makaleler ve Yazarlar

$yazarlar = array();
$ayriTut = array();

$dizin = opendir('makaleler');
while($dosya = readdir($dizin)) {
	if($dosya !== "." && $dosya !== "..") {array_push($yazarlar, $dosya);}
}
$tumYazarBilgileri = array();
for ($i=0; $i < count($yazarlar); $i++) {
	$yazar = opendir('makaleler/'.$yazarlar[$i]);
	while($dosya = readdir($yazar)) {
		if($dosya !== "." && $dosya !== "..") {


			$haber = fopen('makaleler/'.$yazarlar[$i].'/'.$dosya, 'r');
			$icerik = fread($haber, filesize('makaleler/'.$yazarlar[$i].'/'.$dosya));
			
			$kelimeTespiti = explode(" ", $icerik);
			$cokKullanilanKelimeler = array_count_values($kelimeTespiti);
			arsort($cokKullanilanKelimeler);
			$a = 0;

			foreach($cokKullanilanKelimeler as $kullanilan => $kez) {
					$eklenebilir = TRUE;
				for ($b=0; $b < count($ayriTut); $b++) {
					if ($kullanilan == $ayriTut[$b]) {
						$eklenebilir = FALSE;
					}
				}
				if ($eklenebilir == TRUE) {
					array_push($tumYazarBilgileri, $yazarlar[$i]."@@@".$kez."@@@".$kullanilan);
					$a++;
					if($a == 1000) {break;}
				}
			}

			fclose($haber);


		}
	}
}

NOT: ayriTut adıyla oluşturduğumuz dizi içerisine girdiğiniz kelimeler aranmaz ve karşılaştırılmaz. Örneğin SPOR kelimesini o diziye kayıt edersek SPOR kelimesi taramalarda dışarıda kalacaktır.

  • opendir() fonksiyonu ile makaleler klasörümüze ve içerisindeki klasörlere ulaşıyoruz.
  • if($dosya !== "." && $dosya !== "..") kısmı ise standart olarak opendir() ile ulaştığımızda bize fazladan üst klasöre de erişebileceğimiz . ve .. adındaki kısımları klasör olarak sunuyor. Onları ayrı tutuyoruz.
  • İlk while döngümüz içerisinde makaleler klasörümüz içerisindeki yazar isimlerimizi oluşturduğumuz yazarlar dizisine atıyoruz.
  • For bölümünde her yazarın her makalesi tek tek dönüyor. Dönen makalelerde belirtilen sayıda (yine $a değişkeni) kadar kelime sıralanıyor. En çok kullanılandan en az kullanılana doğru gidiyor yine. Tüm bu bilgiler de $tumYazarBilgileri değişkenine şöyle aktarılıyor: YAZAR A@@@15@@@SPOR

3. Karşılaştırma

Bu adımda ise $tumYazarBilgileri ile $arananYazarKim dizileri karşılaştırılır ve ortak kelimeler taranır.

for ($m=0; $m < count($arananYazarKim); $m++) { 
	$kelime = explode("@@@", $arananYazarKim[$m]);
	$adet = $kelime[0]; $kelime = $kelime[1];
	for ($s=0; $s < count($tumYazarBilgileri); $s++) { 
		$kelime2 = explode("@@@", $tumYazarBilgileri[$s]);
		$yazar = $kelime2[0]; $Yadet = $kelime2[1]; $Ykelime = $kelime2[2];
		if (!isset($final[$yazar])) {
			$final[$yazar] = 0;
		}
		if ($kelime == $Ykelime) {
			$final[$yazar] = $final[$yazar]+$Yadet;
		}
	}
}
  • İç içe 2 for döngüsü ile tamamlanan bu yapımızda ilk for döngüsü aranan makaleye ait bilgileri getirirken, ikinci for döngüsü kayıtlı makalelerden getirilen verileri temsil eder.
  • En içte yapılan karşılaştırma ise kullanım adetine göre bir puan oluşturur. Yani örneği YAZAR A'nın eski makalelerinde SPOR kelimesi 15 kez, FUTBOL kelimesi 20 kez kullanılmış olsun. O zaman aranan makale de eğer SPOR ve FUTBOL kelimeleri geçiyorsa YAZAR A'ya 15+20 = 35 puan verilir. Böylece tüm kelimeler karşılaştırılır. Bir yazar muhakkak diğerlerinden daha fazla puana ulaşacaktır.

4. Sonuç

Artık işi yüzdelik dilimlere bölmek, stil katmak ve ekrana çıktı vermek istiyoruz.

$finalPuanlar = array_values($final);
$toplamPuan = 0;
for ($t=0; $t < count($finalPuanlar); $t++) {$toplamPuan = $toplamPuan+$finalPuanlar[$t];}
$sira = 0;
foreach ($final as $yazar => $puan) {
	$ihtimal = $puan/$toplamPuan*100;
	$sira++;
	echo '<div class="tam"><div class="kutu" style="width: calc('.$ihtimal.'% - 30px)">(%'.$ihtimal.') '.$yazar.'</div></div>';
	if($sira == 9) {$sira = 0;}
}
  • Tüm puanlar yüzdelik cinse çevrildi.

Aşağıdaki gibi basit bir stil ataması yapıldı.

.tam {width: 100%; background: #e0e0e0; margin-bottom: 2px;}
.kutu {padding: 0 15px; font: bold 14px/48px Arial; background: #b71c1c; color: #fff; text-align: right;}

Ekranımıza aşağıdaki gibi bir çıktı alabiliriz;

Görüldüğü üzere aranan makaleyi inceleyerek yazması en olası yazarımızı YAZAR A olarak belirledi ve bu doğru. Bu bir ihtimaldir. Yani bunda %100 doğru gibi bir cümle kuramayız. Burada kurulan fonksiyonlar geliştirilebilir ve üstüne eklenerek olasılık arttırılabilir lakin temeli kavramanız açısından böyle bir örnek ile metin madenciliğinin nasıl yapıldığını açıklamak istedim. Okuyup inceleyen herkese teşekkürler, iyi çalışmalar.

YORUMLAR 4
2
Mert Topuz
07 AĞUSTOS 2017 - 14.55
@Ahmet Can, teşekkürler :)
CEVAPLA
1
Ahmet Can
06 AĞUSTOS 2017 - 17.50
Çok başarılı bir anlatım tebrik ederim kardeşim
CEVAPLA
1
Mert Topuz
06 AĞUSTOS 2017 - 11.40
@Volkan ATABEY, Ben teşekkür ederim güzel yorumunuz için Volkan Bey
CEVAPLA
1
Volkan ATABEY
05 AĞUSTOS 2017 - 19.15
güzel yazı teşekkürler
CEVAPLA
YORUM BIRAK
Şuanda bu yoruma cevap yazıyorsunuz:
İptal Et