Cloudera Hadoop Developer Eğitimi

Daha önce eğitimlerinden bahsedilen Cloudera’nın Türkiye’deki tek eğitim partneri olan Dilişim, Apache Hadoop geliştirici eğitimini 22-25 Eylül 2014 tarihlerinde İstanbul’da gerçekleştirecek.

dilisim-clouderaEğitim süresince:

  • Hadoop’un çekirdek teknolojileri HDFS ve MapReduce’un işleyişleri ve MapReduce kodu yazımı
  • Hadoop geliştirmek, hata ayıklamak, iş akışı ve yaygın algoritmaların gerçekleştirilmesi için en iyi pratikler
  • Hive, Pig, Sqoop, Flume, Oozie, Mahout ve diğer Hadoop ekosistem projelerinden faydalanmak
  • Hadoop kümesini veri merkezine entegre etmek için en uygun donanım ve ağ yapılandırması
  • Veri setlerini birleştirme için MapReduce’da join operasyonu yazma ve yürütme
  • Gerçek-dünya veri analizi için gereken ileri Hadoop API konuları üzerinde yoğunlaşıp, belirtilen konularla ilgili sınıf ortamında alıştırmalar yapılacak.

Gereken donanım, örneğin eğitim süresince kullanılacak bilgisayarlar Dilişim tarafından sağlanacak.

Eğitime katılanlar Cloudera Certified Developer in Apache Hadoop (CCDH) deneme sınavına ücretsiz giriş hakkı kazanacak.

Eğitim, sunum materyalleri İngilizce olmakla birlikte, Türkçe gerçekleşecek.

cloudera-logo

Cloudera’nın resmi eğitimini Türkçe olarak yetkilisinden almayı; bu konuda sertifikalı olmak ve eğitim almak isteyen arkadaşlar için büyük bir fırsat olarak görüyorum.

Eğitim hakkında detaylı bilgiye buradan ulaşabilirsiniz.

Eğitime ön kayıt yaptırmak için ise bu linki kullanabilirsiniz.

Facebook Presto

presto-ogPresto, Facebook tarafından geliştirilmiş ve açık kaynaklı hale getirilmiş bir proje. Presto da diğer Dağıtık SQL motoru çözümleriyle (Impala, Drill, Spark SQL) aynı amacı güdüyor ve mimari olarak da olduça benzer. Hive projesini de Facebook’un geliştirdiğini düşünecek olursak projeden beklentimiz oldukça yüksek. Ancak arkasında bir topluluk veya ticari bir firma olmadığı için de geleceği konusunda kafamızda bir soru işareti olmuyor değil. Örneğin dökümantasyonunun yetersiz olduğunu söyleyebiliriz. Ancak en iyisi (ve keyiflisi) kendimizin deneyerek karar vermesi. Presto hali hazırda Hive ve Cassandra ile entegre olabiliyor. Bu yazımızda Presto’nun kurulumu ve Hive ile entegrasyonunu anlatacağız.

Kurulum ve konfigürasyon

Prestonun şu andaki en güncel hali olan 0.75 sürümünü buradan veya komut satırından indirmekle başlayalım:

wget http://central.maven.org/maven2/com/facebook/presto/presto-server/0.75/presto-server-0.75.tar.gz
tar xvf presto-server-0.75.tar.gz

Presto’nun kurulumu biraz karışık. Metadata’yı saklaması için bir data dizini, bir de konfigürasyon için etc dizini oluşturmamız gerekiyor. Nedense diğer projelerden alışık olduğumuz konfigürasyon şablonlarını kuruluma dahil etmemişler. Bunları bizim oluşturmamız gerekiyor. Bu amaçla etc dizini içerisinde node.properties, jvm.config ve config.properties isimli üç dosya yaratacağız. etc/node.properties dosyası içerisinde node.id ile her düğümün tekil id’sini belirtiyoruz. node.data-dir ile de data dizinini belirtiyoruz:

node.environment=test
node.id=node1-presto
node.data-dir=/opt/presto/data

etc/jvm.config dosyası ile jvm ayarlarını yapıyoruz. Burada Xmx parametresini sunucunun hafıza kaynaklarına göre vermemiz gerekiyor, aksi taktirde OutOfMemory hatası ile karşılaşmamız normaldir:

-server
-Xmx2G
-XX:+UseConcMarkSweepGC
-XX:+ExplicitGCInvokesConcurrent
-XX:+CMSClassUnloadingEnabled
-XX:+AggressiveOpts
-XX:+HeapDumpOnOutOfMemoryError
-XX:OnOutOfMemoryError=kill -9 %p
-XX:PermSize=150M
-XX:MaxPermSize=150M
-XX:ReservedCodeCacheSize=150M
-Xbootclasspath/p:/var/presto/installation/lib/floatingdecimal-0.1.jar

etc/config.properties içerisinde ise Presto süreçleri ile ilgili ayarları yapıyoruz. Presto süreçleri Coordinator ve Worker süreçlerinden oluşuyor. Coordinator sürecini NameNode sunucusunda, Worker süreçlerini de DataNode sunucularında çalıştırmak mantıklı olabilir. Presto düğümleri birbirlerini Discovery Service üzerinden bulurlar. Bunu yaparken de tüm haberleşme http üzerinden yapılıyor. Bu yüzden ayarlar farklılaşıyor. Coordinator düğümünde ayarlar şöyle:

coordinator=true
node-scheduler.include-coordinator=false
http-server.http.port=8080
task.max-memory=1GB
discovery-server.enabled=true
discovery.uri=http://hostname:8888

Worker düğümünde ise şu şekilde olmalı:

coordinator=false
http-server.http.port=8080
task.max-memory=1GB
discovery.uri=http://hostname:8888

Burada önemli parametrelerden birisi olan task.max-memory ile o sırada işlenen sorgu için kullanılabilecek maksimum hafıza miktarını belirtiyoruz. Özellikle group by, order by ve join işlemlerinde performans amacıyla işlemlerin tamamı hafızada yapıldığı için bu parametre doğru kullanılmalı. Az hafıza verilirse sorgular OutOfMemory hatası alıp tamamlanmayabilir.

Bitti sanıyorsanız yanılıyorsunuz. Bunların dışında ayrıca bir de Discovery servisini indirip kurmamız gerekiyor. Neden birlikte paketlenmediklerini, dökümantasyonda bu adımların neden olmadığı sorusunu kendi kendinize sorabilirsiniz.

wget http://central.maven.org/maven2/io/airlift/discovery/discovery-server/1.16/discovery-server-1.16.tar.gz
tar xvf discovery-server-1.16.tar.gz
ln -s /opt/presto/discovery-server-1.16 /opt/presto/discovery
mkdir /opt/presto/discovery/data /opt/presto/discovery/etc

Discovery servisi için de ayar dosyaları şu şekilde; discovery/etc/node.properties dosyası:

node.environment=test
node.id=node1-discovery
node.data-dir=/opt/presto/discovery/data

discovery/etc/config.properties dosyası:

http-server.http.port=8888

Bir de jvm.config ayarları:

-server
-Xmx1G
-XX:+UseConcMarkSweepGC
-XX:+ExplicitGCInvokesConcurrent
-XX:+AggressiveOpts
-XX:+HeapDumpOnOutOfMemoryError
-XX:OnOutOfMemoryError=kill -9 %p

Son olarak bu ayarların dışında Presto ile sorgulamak istediğimiz verileri catalog ayarları ile tanımlamamız gerekiyor. Biz Hive ile entegre olacağımız için catalog dizini altına ilgili ayar dosyasını oluşturacağız.

Hive ile Entegrasyon

Devam etmeden önce Hive tarafında örnek tabloyu oluşturmak için her zaman kullandığımız NYSE verisini indirdikten sonra hive konsolundan şunları çalıştırabilirsiniz:

CREATE TABLE nyse (exchangeSymbol string, stockSymbol string, stockDate string, stockPriceOpen double, stockPriceHigh double, stockPriceLow double, stockPriceClose double, stockVolume int, stockPriceAdjClose double) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' STORED AS TEXTFILE;

LOAD DATA LOCAL INPATH '/Users/devveri/dev/test/NYSE-2000-2001.tsv' OVERWRITE INTO TABLE nyse;

Hive ile ilgili daha fazla bilgiye ihtiyacınız varsa (biraz eskimiş de olsa) ilgili yazımıza bakabilirsiniz. Presto Hive’ın birçok farklı sürümünü destekliyor. Bunlar hive-hadoop1, hive-hadoop2, hive-cdh4, hive-cdh5 olarak zaten plugins klasörü altında görülebilir. Hive entegrasyonu için etc/catalog/hive.properties dosyasını oluşturuyoruz:

connector.name=hive-hadoop2
hive.metastore.uri=thrift://metastorehost:9083

hive.metastore.uri parametresi ile Hive metastore thrift adresini belirtiyoruz. Eğer daha önce yapmadıysanız Hive metastore servisini çalıştırmak için aşağıdaki komutu kullanabilirsiniz:

/opt/hive/bin/hive --service metastore

Presto süreçlerini başlatma ve durdurma

Presto süreçlerini başlatmak ve durdurmak için komut satırını kullanıyoruz:

bin/launcher start
bin/launcher stop

Küme olarak çalışması için Discovery servisinin de ayrıca başlatılması gerekiyor:

discovery/bin/launcher start

Log dosyalarını takip etmek isterseniz:

tail -f data/var/log/*

Presto komut satırı kullanımı

Bu kısım çok ilginç. Presto’yu komut satırından kullanmak isterseniz ilgili jar dosyasını ayrıca indirmeniz gerekiyor. Hangi kafayla bunu yaptıklarını gerçekten çok merak ediyorum. Neyse ki sizin için aşağıdaki komutları hazırladım:

wget http://central.maven.org/maven2/com/facebook/presto/presto-cli/0.75/presto-cli-0.75-executable.jar
chmod +x presto-cli-0.75-executable.jar
echo ./presto-cli-0.75-executable.jar --server localhost:8080 --catalog hive --schema default > presto-cli.sh

Artık presto-cli.sh ile Presto’ya istemci olarak bağlanabilir ve sorgularınızı çalıştırabilirsiniz:

$ ./presto.sh 
presto:default> show tables;
 Table 
-------
 nyse 
(1 row)

Query 20140827_215335_00015_96n4f, FINISHED, 1 node
Splits: 2 total, 2 done (100.00%)
0:00 [1 rows, 93B] [10 rows/s, 947B/s]

presto:default> select * from nyse limit 10;
 exchangesymbol | stocksymbol | stockdate | stockpriceopen | stockpricehigh | stockpricelow | stockpriceclose | stockvolume | stockpriceadjclose 
----------------+-------------+------------+----------------+----------------+---------------+-----------------+-------------+--------------------
 NYSE | ASP | 2001-12-31 | 12.55 | 12.8 | 12.42 | 12.8 | 11300 | 6.91 
 NYSE | ASP | 2001-12-28 | 12.5 | 12.55 | 12.42 | 12.55 | 4800 | 6.78 
 NYSE | ASP | 2001-12-27 | 12.59 | 12.59 | 12.5 | 12.57 | 5400 | 6.79 
 NYSE | ASP | 2001-12-26 | 12.45 | 12.6 | 12.45 | 12.55 | 5400 | 6.78 
 NYSE | ASP | 2001-12-24 | 12.61 | 12.61 | 12.61 | 12.61 | 1400 | 6.76 
 NYSE | ASP | 2001-12-21 | 12.4 | 12.78 | 12.4 | 12.6 | 18200 | 6.75 
 NYSE | ASP | 2001-12-20 | 12.35 | 12.58 | 12.35 | 12.4 | 4200 | 6.65 
 NYSE | ASP | 2001-12-19 | 12.42 | 12.6 | 12.35 | 12.6 | 10100 | 6.75 
 NYSE | ASP | 2001-12-18 | 12.37 | 12.5 | 12.37 | 12.41 | 10100 | 6.65 
 NYSE | ASP | 2001-12-17 | 12.4 | 12.52 | 12.4 | 12.52 | 8000 | 6.71 
(10 rows)

Query 20140827_215344_00016_96n4f, FINISHED, 1 node
Splits: 2 total, 2 done (100.00%)
0:01 [4.37K rows, 234KB] [5.82K rows/s, 312KB/s]

presto:default> select stockSymbol, sum(stockPriceClose) as total_value from nyse where stockVolume > 1000 group by stockSymbol order by total_value desc limit 10;
 stocksymbol | total_value 
-------------+--------------------
 WPO | 267022.80000000005 
 WTM | 117073.61 
 MTB | 106871.27 
 MKL | 82668.22 
 PC | 67790.19999999998 
 KYO | 60137.99999999997 
 JNPR | 59107.12999999994 
 BCS | 57008.43000000009 
 NVR | 56314.829999999994 
 SPW | 56300.86999999995 
(10 rows)

Query 20140827_215533_00018_96n4f, FINISHED, 1 node
Splits: 3 total, 3 done (100.00%)
0:04 [813K rows, 42MB] [217K rows/s, 11.2MB/s]

Bundan sonrasında Presto’yu incelemek, performans karşılaştırmaları yapmak size kalıyor. Bu yazımızı sevdiyseniz Spark SQL ve Impala yazılarımız da ilginizi çekebilir. Presto ile ilgili ayrıntıları kendi sitesinde bulabilirsiniz.

Spark SQL

spark-logoApache Spark projesinin yeteneklerinden birisi de SQL ve HiveQL arayüzleri ile veri işleyebilmesi. Yazıyı yayınlamadan önce bu proje Shark olarak isimlendiriliyordu, ancak ismi değiştirilerek Spark SQL olarak adlandırıldı ve mevcut projeye dahil edildi.

Spark SQL Hive, Impala, Drill projelerine bir alternatif oluşturuyor. JSON, Parquet vs gibi populer tüm veri tiplerini destekliyor. Ayrıca Hive metadata’sını da kullanabildiği için Hive tablolarını Spark SQL ile sorgulamak mümkün.

Spark yazımızda verilerin RDD’ler üzerinden işlendiğinden bahsetmiştik. SQL arayüzü için de SchemaRDD (Java için JavaSchemaRDD) tipini kullanıyoruz. Veriyi RDD olarak yükledikten sonra tablo olarak register ediyoruz, ardından bu tablo üzerinde SQL komutununu çalıştırabiliyoruz. SQLContext üzerinde sorgumuzu çalıştırdıktan sonra veri bize Row tipinde dönüyor.

Örnek amaçlı olarak daha önce de kullandığımız NYSE verilerini kullanacağız. Bu veriye karşılık gelen ExchangeRecord sınıfını yazdıktan sonra veriyi aşağıdaki gibi sorgulayabiliriz:

package com.devveri.spark.job;

import com.devveri.spark.model.ExchangeRecord;
import com.devveri.spark.util.SparkHelper;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.sql.api.java.JavaSQLContext;
import org.apache.spark.sql.api.java.JavaSchemaRDD;
import org.apache.spark.sql.api.java.Row;

import java.util.List;

public class NYSEExample {

    public static void main(String[] args) throws Exception {
        final String appName = "NYSEExample " + System.currentTimeMillis();
        final String stockFile = "file:///Users/devveri/dev/test/NYSE-2000-2001.tsv";

        // get contexts
        JavaSparkContext jsc = new JavaSparkContext(SparkHelper.getDefaultConf()); 
        JavaSQLContext sqlContext = new JavaSQLContext(jsc);

        // load data and convert to java object
        JavaRDD exchanges = jsc.textFile(stockFile).map(new Function<String, ExchangeRecord>() {
            public ExchangeRecord call(String s) throws Exception {
                return new ExchangeRecord(s);
            }
        });

        // apply schema
        JavaSchemaRDD schemaExchange = sqlContext.applySchema(exchanges, ExchangeRecord.class);
        schemaExchange.registerAsTable("exchanges");

        // execute an sql query
        JavaSchemaRDD topExchanges = sqlContext.sql(
                "select stockSymbol, sum(stockPriceClose) as total_value " +
                "from exchanges " +
                "where stockVolume > 1000 " +
                "group by stockSymbol " +
                "order by total_value desc " +
                "limit 10");

        List result = topExchanges.map(new Function<Row, String>() {
            public String call(Row row) throws Exception {
                return String.format("%s\t%f",
                        row.getString(0),
                        row.getDouble(1));
            }
        }).collect();

        for (String s : result) {
            System.out.println(s);
        }
    }

}

SQLContext sadece basit SQL cümlelerini destekliyor. Daha kompleks SQL cümleleri gerekirse HiveContext kullanmak gerekiyor.

Spark SQL, Hive uyumluluğu, SerDe desteği, JSON, Parquet dosyalarında direk destek vermesi, farklı projelerle olan entegrasyonu (Cassanda gibi) oldukça yetenekli görünüyor. Özellikle SQL arayüzü desteklemeyen projelere entegre ederek çok başarılı sonuçlar elde edilebilir. Sadece benchmark’lara baktığımızda performans olarak benzer projelerin önüne geçemediğini görüyoruz.

Daha fazla detay için dökümantasyona buradan erişebilirsiniz.

Apache Nutch

Tarihçe ve Tanım

nutch_logo_mediumDev veriden bahsedildiğinde Hadoop’un başlangıç projesi olan Nutch’tan söz etmemek olmaz. “Hadoop nasıl başladı?” sorusunun cevabı bizi Nutch isimli Apache projesine götürür. Nutch’ın temelleri ise Google arama motoru yapmak için işe başlandığında bunun en hızlı şekilde yapabilmesi için GFS ve MapReduce teknolojilerinin yayınlaması ile atıldı. Peki Nutch için HDFS ve MapReduce neden gerekli? Bir crawlera sahipseniz büyük veriye sahipsiniz demektir. Bir çok sitenin içeriğine sahip olmak ve bunlar üzerinden kolayca işlem yapabilmek için dağıtık bir sisteme ihtiyacınız vardır; bunun da en güzel yolu HDFS ve MapReduce’dur.

Projenin nasıl çalıştırılıp ve istenilen çalışma şekline nasıl getirileceği konularında bilgi vermeye çalışacağım. Anlatımlarım linux işletim sistemi üzerinden olacaktır. İşletim sisteminize uymuyorsa veya sorun yaşıyorsanız işletim sisteminiz üzerine Virtual Machine araçları (VMWareVirtualBox vs.) ile Ubuntu-12.04.4 kurup sıfır bir işletim sistemi ile deneyebilirsiniz.

İndirme ve Derleme

1) Öncelikle projenin kaynak kodunu Apache’nin sitesinden indirmeniz gerekmekte.

link : http://www.apache.org/dyn/closer.cgi/nutch/

Anlatımlarım apache-nutch-1.8 verisonun src’si için olacak. Projeyi indirdikten sonra bilgisayarınızda istediğiniz bir konuma zip’ten çıkartın.

2) Bilgisayarınızda JAVA_HOME ‘un ayarlı olması gerekiyor.

export JAVA_HOME=$(readlink -f /usr/bin/java | sed "s:bin/java::")

komutunu çalıştırın veya ~/.bashrc dosyanıza bu komutu ekleyin.

3) Komut satırından projenizin bulunduğu klasöre gidin

$cd apache-nutch_Xsurum/

4)  $ant runtime komutunu çağırın ve projenizin bulunduğu klasörde runtime/local şeklinde bir klasör oluşmuş olması gerekiyor.

Not: ant bulunamadı hatası aldıysanız $sudo apt-get install ant komutunu çağırın ve tekrar deneyin.

Ayarlamalar için gerekli Config dosyalarıda runtime/local/conf/ klasörü altında bulunuyor. Hatırlatmakta fayda var $ant clean komutunu çalıştırmaya gerek duyduğunuzda runtime dosyası silineceğinden ant clean komutunu çalıştırmadan önce config dosyalarınızı yedekleyin.

Kontrol

Komut satırından runtime/local içinde iken $bin/nutch yazın, eğer bir sorun yoksa aşağıdaki ifadeyi görmeniz gerekmekte.

Usage: nutch COMMAND where COMMAND is one of:

readdb            read / dump crawl db
mergedb           merge crawldb-s, with optional filtering
readlinkdb        read / dump link db
inject            inject new urls into the database
generate          generate new segments to fetch from crawl db
freegen           generate new segments to fetch from text files
fetch             fetch a segment's pages
parse             parse a segment's pages

Erişim izni hatası alırsanız $chmod +x bin/nutch kodunu çalıştırıp tekrar deneyin.

Nutch Ayarları

1) Nutch için belirlenmiş default ayarları conf/default.xml dosyasının içinde bulabilirsiniz. Buradaki ayarlardan size gereken ayarı kullanmak için ise conf/nutch-site.xml ‘e o ayarı kopyalamanız gerekmekte.

Projemizi ilk kez çalıştırmadan önce bazı ayarlar yapmamız gerekmekte.

http.agent.name property ayarı yapmak için conf/nutch-site.xml dosyamıza aşağıdaki kodu kopyalayalım ve kaydedelim.

<property>
<name>http.agent.name</name>
<value>My Nutch Spider</value>
</property>

2) Nutch bize içeriğini çekeceğimiz siteleri belirlememiz için kolay bir yol sunmakta. Text dosyasına satırlar halinde içeriğini çekmek istediğimiz siteleri yazmamız gerekiyor. Bunun için aşağıdaki komutları çalıştırabilirsiniz veya normal yoldan runtime/local/ dosyası içine urls klasörü yaratıp içine seed.txt adında bir text file yaratıp içine satırlar halinde urlleri yazabilirsiniz.

$mkdir -p urls
$cd urls
$touch seed.txt

Bu komutlarla runtime/local/urls/seed.txt adında bir dosya yaratmış olduk içine içeriğini istediğiniz sitelerin urllerini yazmanız gerekiyor. Urllerin başlarında http:// olmasına dikkat edin yoksa hata alabilirsiniz. Örnek olarak http://devveri.com/ yazıp kaydediyoruz.

3) İsterseniz sitenin içinde istediğiniz şekilde bir veri alımı için regex yazabilirsiniz. Bunu yapmak için conf/regex-urlfilter.txt dosyasını açıp en alt kısımdaki;

# accept anything else

+.

yerine

+^http://([a-z0-9]*\.)*devveri.com/

yazabilirsiniz. Bu regex programınızın sadece site içinde bulduğu linklerden sitenin dışına çıkan linklerin içeriğine gitmeme faydası sağlar. Bu kısmı böyle bir dosyanın var olduğunu bilmeniz için anlattım +. şeklinde kalabilir.

Solr Ayarları

Anlatımımda çektiğiniz içerikler direk solra indexlenecektir.Bunun için localinizdeki solr ın schema.xml’ini ayarlamamnız gerekmekte. Nutch’ın Solr 4.3.0 ile sorunsuz çalıştığı söylenmekte bunun için localinizdeki Solr’ın bu versiyon olduğunu kabul edip anlatımıma devam ediyorum. Eğer mevcut değilse derlenmiş Solr 4.3.0′ı indirmeniz grekmekte. Derlenmiş 4.3.0 İndirmek için link :

http://archive.apache.org/dist/lucene/solr/4.3.0/

Nutch dosyanızdaki conf/schema-solr4.xml dosyasını Solr ın bulunduğu klasördeki schema.xml ile değiştirmeniz gerekiyor. Öncelikle solrın bulunduğu klasördeki schema.xml dosyanızın ismini schema.xml.org olarak değiştirip sonrasında  yerine conf/schema-solr4.xml dosyasını kopyalayıp ismini schema.xml olarak değiştirmenizi tavsiye ederim.

Sonrasında değiştridiğiniz yeni schema.xml ‘in 351. satırına

<field name="_version_" type="long" indexed="true" stored="true"/>

ifadesini ekleyiniz.

Solr’ı yeni bir komut penceresinde çalıştırın.

$java -jar start.jar

Nutch Akış Şeması

 

nutch _flowchartProje urls/seed.txt içerisinde tanımladığınız url’leri crawldb ‘ye koyar ve MapReduce çalıştırarak koyduğunuz sitenin içeriğini çekmeye başlar. Yukarıda ki şemada görülen döngünün sayısını siz verdiğiniz parametre ile belirlersiniz. Her döngü sonunda index güncellenir ve solr paremetre olarak verildiyse ilk döngü bittiğinde solr’ın panelinden ilk indexlerin geldiğini görebilirsiniz.

Crawl Komutu ile Çalıştırma

1) Artık projemizi belirlediğiniz sitenin içeriğini almak için çalıştırabiliriz.

$bin/crawl urls/seed.txt testcrawl http://localhost:8983/solr/ 2

Buradaki 2 değerini döngü sayısı gibi düşünebilirsiniz. Elinizde başlangıçta anasayfa url var.İlk döngüde anasayfanın içeriğini alır ve bulduğu linkleride ikinci döngüye hazırlar. İkinci döngüde birinciden gelen yeni urllerin içeriklerini alır ve bulduğu urlleri diğer döngüye hazırlar. 2 dersek proje burada durur. Aynı şekilde tekrar çalıştırdığımızda son kaldığı yerden 2 döngü daha atarak ilerler. 2 sayısının yerine bir seferde kaç döngüde çalışmasını istiyorsanız yazabilirsiniz.

2) Komutu çalıştırdığınızda MapReduce’un işlediğini göreceksiniz ve işlem bittiğinde aşağıdaki gibi yaratılmış bir dosya düzenine sahip olacaksınız.

testcrawl/crawldb
testcrawl/linkdb
testcrawl/segments

Nutch Komutu ile Çalıştırma

Projenizi $bin/nutch komutu ilede çalıştırabilirsiniz ama önerilmeyen bir çalışma biçimidir.

$bin/nutch crawl urls -dir crawl -depth 3 -topN 5

Komutunu çalıştırın

** depth anasayfadan ne kadar derine ineceğini gösterir.

Örnek : Anasayfada 111.html linki var bu sayfada 222.html linki var vs

Kısaca anasayfadan başlayıp her bulduğu linkinde içeriğini alıp onların götürdüğü linklerin içeriğinide alacakmı ne kadar derine gidecek depth onun ayarlanması içindir.

**topN ise her derinlikte maximum ne kadar url in yeni içerik alma listesine ekleneceğinin ayarıdır.

$bin/nutch crawl2 urls -solr http://localhost:8983/solr/ -depth 3 -topN 5

Not: crawl2 yazmamın sebebi solr olmadağan çalıştırdığımız komut crawl dosyası içinde veriler yaratmıştı ikinci kez crawl yazarsak ilk crawlda bulduğu veriler üzerinden devam eder.

Faydalı Bilgiler

*runtime/deploy klasörüde dikkatinizi çekmiştir. Eğer aynı komutları burada çalıştırmak isterseniz. urls klasörünün hdfs te olması gerekiyor. Ve sonuç crawl dosyanız hdfs e yazılır.

* nutch-site.xml den nasıl faydalanabileceğiniz konusunda birkaç örnek vereyim.

—Yazının başında yazdığımız regex in yaptığı iş için böyle bir ayar mevcut crawl işlemi esnasında value true ise sitenin dışına çıkmadan crawl işlemini gerçekleştirmeye yarıyor.

<property>
<name>db.ignore.external.links</name>
<value>false</value>
<description>If true, outlinks leading from a page to external hosts
will be ignored. This is an effective way to limit the crawl to include
only initially injected hosts, without creating complex URLFilters.
</description>
</property>

—Aynı sunucuya atılan ardışık isteklerdeki bekleme süresi

<property>
<name>fetcher.server.delay</name>
<value>5.0</value>
<description>The number of seconds the fetcher will delay between
successive requests to the same server.</description>
</property>

*Nutch crawl surecinin adimlarını merak ediyorsanız daha detaylı bilgi için

http://wiki.apache.org/nutch/NutchTutorial inceleyebilirsiniz.

Apache Spark

spark-logoApache Spark bugünlerde ismini daha sık duymaya başladığımız, büyük veri işleme amaçlı bir diğer proje. Hadoop’tan 100 kat daha hızlı olmak gibi bir iddia ile birlikte, gelişmiş “Directed Acyclic Graph” motoruna sahip, Scala dili ile yazılmış ve bellek-içi (in-memory) veri işleme özellikleriyle bu iddiayı boşa çıkartmıyor gibi görünüyor. Özellikle Yapay Öğrenme algoritmalarının dağıtık implementasyonu konusunda Hadoop’tan daha performanslı olduğunu söyleyebiliriz. Öyle ki, Apache Mahout projesi bundan böyle Hadoop ile değil Spark üzerinde çalışacak şekilde geliştirilmeye etme kararı aldı.

Ancak şunu söylemeliyiz ki Spark Hadoop’un yerine geçecek bir teknoloji olmaktan ziyade, Hadoop ailesinin bir üyesi olup Hadoop’un zayıf kaldığı bazı konulardaki eksiklikleri giderecek gibi görünüyor. Hadoop binlerce sunucu üzerinde petabyte’larca veriyi stabil şekilde saklayıp analiz edebilecek şekilde tasarlanmışken, Spark göreceli olarak daha az miktarda veriyi özellikle in-memory olarak işlemek ve daha hızlı sonuç almak amacıyla tasarlanmış. Spark HDFS gibi herhangi bir storage çözümü sunmuyor ancak HDFS üzerinden okuma yazma yapabiliyor. Java ile Hadoop MapReduce uygulamaları geliştirmek çok low-level sayılırken, Spark ile bir uygulama geliştirmek çok daha kullanıcı dostu. Bu yüzden Spark’ı alet çantamızdaki farklı bir araç olarak görmemiz gerektiğini düşünüyorum.

logistic-regression
Logistic regression algoritmasının Hadoop ve Spark üzerinde çalıştırılması sonucu elde edilen performans örneklenmiş. 

Spark kümesini standalone çalıştırmanın dışında Amazon EC2, Mesos ve YARN ile beraber çalıştırmanız mümkün. Dilerseniz test amaçlı olarak tek sunucuda lokal modunda da çalıştırabilirsiniz. Küme olarak çalıştırdığınızda bir master ve birden çok slave düğümü oluyor. Slave düğümlerinde kaç worker çalışacağını, bunların kaç cpu core ve ne kadar memory kullanacağını ayarlayamanız gerekiyor.

Uygulama geliştirme açısından Spark Scala’nın avantajlarını sonuna kadar kullanıyor. Örneğin artık “hello world” uygulaması yerine geçen “word count” uygulamasını Spark ile çok az bir kod parçası ile gerçekleştirebiliyoruz:

val file = spark.textFile("hdfs://...")
val counts = file.flatMap(line => line.split(" "))
 .map(word => (word, 1))
 .reduceByKey(_ + _)
counts.saveAsTextFile("hdfs://...")

Scala dışında Java ve Python dillerini de destekliyor. En güzel özelliklerinden birisi Spark’ın getirdiği soyutlama ile geliştirme yapmanın çok kolay hale gelmesi. Esnek Dağıtık Verisetleri ile (Resilient Distributed Dataset, kısaca RDD) veriyi sanki bir collection objesini işler gibi işlememiz sağlanmış. RDD’ler veri işlemeyi kolaylaştıracak map, filter, union, cartesian, join, groupByKey, sortByKey gibi birçok transformasyon metodunun yanı sıra, reduce, collect, count, distinct gibi aksiyon metodlarını içeriyor. Bir dosyayı veya bir collection objesini RDD’ye çevirip bu metodları ardışıl bir şekilde çağırarak veriyi işliyoruz. Transformasyon metodları lazy tasarlanmış, yani herhangi bir aksiyon metodu çağırılana kadar gerçekte bir işlem yapılmıyor. Spark uygulamalarını interaktif arayüzü (spark-shell) üzerinden test etmek mümkün. Örnek uygulamalara gözatabilirsiniz.

Java ile “word count” uygulaması örneği ise şöyle:

package com.devveri.spark;

import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.FlatMapFunction;
import org.apache.spark.api.java.function.Function2;
import org.apache.spark.api.java.function.PairFunction;
import scala.Tuple2;

import java.util.Arrays;
import java.util.regex.Pattern;

/**
 * Created by hilter on 11/05/14.
 */
public class WordCount {

 private static final String MASTER = "spark://localhost";

 private static final Pattern SPACE = Pattern.compile(" ");

 public static void main(String[] args) {
 // create context
 JavaSparkContext jsc = new JavaSparkContext(
 MASTER,
 "WordCount",
 System.getenv("SPARK_HOME"),
 JavaSparkContext.jarOfClass(WordCount.class)
 );

 // load file
 JavaRDD<String> file = jsc.textFile("/Users/devveri/test.txt");

 // split words
 JavaRDD<String> words = file.flatMap(new FlatMapFunction<String, String>() {
 public Iterable<String> call(String s) { return Arrays.asList(s.split(" ")); }
 });

 // create pairs
 JavaPairRDD<String, Integer> pairs = words.map(new PairFunction<String, String, Integer>() {
 public Tuple2<String, Integer> call(String s) { return new Tuple2<String, Integer>(s, 1); }
 });

 // count
 JavaPairRDD<String, Integer> counts = pairs.reduceByKey(new Function2<Integer, Integer, Integer>() {
 public Integer call(Integer a, Integer b) throws Exception { return a + b; }
 });

 // save result
 counts.saveAsTextFile("/tmp/result");
 }

}

Java 8′in yeni özelliklerinden faydalanmadığınız durumda Java ile Spark uygulaması geliştirmek böyle çirkin kodlar yazmanıza sebep oluyor, ancak çalışmasında herhangi bir performans farkı sözkonusu değil.

Örnekte ilk olarak bir JavaSparkContext objesi oluşturuyoruz. Sonrasında bir metin dosyasını yükleyip her bir satır bir String objesi olacak şekilde bir RDD oluşturuyoruz. Yüklenen her bir satırı flatMap metodu içerisinde yazdığımız fonksiyonda boşluklarından ayrılıyor, flatMap metodu da her bir elemanı birer satır haline dönüştürüyor. Kelime sayısını alabilmek için bu satırları map metoduna vererek [kelime, 1] formatında bir pair objesi haline getiriyoruz. Sonrasında reduceByKey metodu ile bu kelimelere karşılık gelen sayıları topluyoruz. En sonunda da sonucu bir metin dosyasına kaydediyoruz. Bütün bu işlemleri master düğümün arayüzünden takip edebilirsiniz.

spark-master

Spark ile ilgili dikkat edilmesi gereken konulardan birisi Spark’ı hangi Hadoop sürümü ile çalıştırmak istediğiniz. Hadoop v1, v2, CDH3, CDH4, CDH5 gibi farklı Hadoop sürümlerine uygun sürümü bulup kurmanız ya da koddan derlemeniz gerekiyor. Aksi takdirde sorun yaşamanız çok muhtemel.

Bunların dışında Spark Streaming özelliği ile aslında Apache Storm projesinin sağladığı sürekli akan verileri anlık olarak işleyebilme özelliğini sağlıyor. Ayrıca Spark, Hive ile entegre olan dağıtık SQL motoru Apache Shark projesinde de altyapı sağlıyor. Son olarak MLlib isimli Yapay Öğrenme ve GraphX isimli çizge veritabanı projeleri de Spark çatısı altında toplanmış.

İlerleyen günlerde Spark daha fazla önümüze çıkacakmış gibi görünüyor.

ElasticSearch ve Pig Entegrasyonu

elasticsearchPig ile sadece Hadoop üzerindeki verileri değil, MongoDB gibi farklı veri kaynaklarını da analiz edebileceğimizden bir yazımızda bahsetmiştik. Pig ile ElasticSearch üzerindeki verileri de analiz etmemiz mümkün. Aynı şekilde Hadoop üzerindeki verileri Pig aracılığı ile ElasticSearch üzerinde kolayca indekslemeniz ve analizler yapmanız oldukça kolay.

Hazırlık

Pig ile ElasticSearch entegrasyonu ile ilgili projeye GitHub üzerinden erişmeniz mümkün. Proje ile sadece Pig değil, Hive ve MapReduce entegrasyonu da gerçekleştirmek mümkün. Build ettikten sonra oluşan elasticsearch-hadoop.jar dosyasını Hadoop’un lib dizini içerisine kopyalamamız gerekiyor. Benim kurulumumda bu klasör /usr/lib/hadoop/lib şeklindeydi.

Maven ile kullanmak istediğinizde aşağıdaki ayarları kullanabilirsiniz.

<dependency>
 <groupId>org.elasticsearch</groupId>
 <artifactId>elasticsearch-hadoop</artifactId>
 <version>2.0.0.BUILD-SNAPSHOT</version>
</dependency>
<repositories>
 <repository>
 <id>sonatype-oss</id>
 <url>http://oss.sonatype.org/content/repositories/snapshots</url>
 <snapshots><enabled>true</enabled></snapshots>
 </repository>
</repositories>

Pig ve Hive ile ElasticSearch verilerini analiz ederken “Speculative Execution” özelliğini devredışı bırakmamız gerekiyor. “Speculative Execution” özelliği MapReduce işlemleri sırasında bir job’un yavaş çalışması durumunda o işin bitmesini veya fail etmesini beklemek yerine aynı anda aynı işi yapacak ve belki daha önce tamamlayacak başka bir job’ın başlatılarak sonucu garantilemeyi amaçlayan bir özellik.

Örnek amaçlı olarak Hortonworks’ün paylaştığı Newyork borsasının 2000-2001 yılı verilerini kullanacağız. Verileri https://s3.amazonaws.com/hw-sandbox/tutorial1/NYSE-2000-2001.tsv.gz adresinden indirdikten sonra HDFS üzerine aktarmamız gerekiyor.

ElasticSearch’e Veriyi Aktarma

ElasticSearch üzerindeki verilere Pig üzerinden erişim için EsStorage sınıfını kullanıyoruz. Bu sınıfın constructor metoduna bağlanacağımız sunucuların adres ve portları, bağlantı timeout değerlerini, indeksin otomatik yaratılıp yaratılmayacağı gibi ayarları veriyoruz.

HDFS üzerinde duran borsa verisini Pig ile yükleyip ElasticSearch’e aktarmak için neredeyse hiçbirşey yapmamıza gerek yok. Pig bizim için herşeyi halletmiş. Tek yapmamız gereken Load komutunu PigStorage sınıfı ile HDFS üzerindeki veriyi yüklemek, daha sonra Store komutunu EsStorage sınıfı ile kullanarak veriyi indekslemek.

REGISTER elasticsearch-hadoop.jar;

/* disable speculative execution */
set mapred.map.tasks.speculative.execution false
set mapred.reduce.tasks.speculative.execution false

DEFINE EsStorage org.elasticsearch.hadoop.pig.EsStorage('es.nodes=localhost:9200');

/* load nyse data */
A = LOAD '$INPUT' USING PigStorage() AS (exchange:chararray, stock_symbol:chararray, stock_date:chararray, stock_price_open:double,
 stock_price_high:double, stock_price_low:double, stock_price_close:double, stock_volume:double, stock_price_adj_close:double);

/* write to elasticsearch */
STORE A INTO '$OUTPUT' USING EsStorage();

ElasticSearch’ten Veriyi Okuma

EsStorage sınıfı ile veriyi okurken indeks içerisinden istediğimiz alanları sanki veritabanından okuyormuş gibi seçebiliyoruz. Hatta sorgu vererek sadece bu sorgunun sonucunu Pig tarafında da analiz etme şansımız bulunuyor.

REGISTER elasticsearch-hadoop.jar;

/* disable speculative execution */
set mapred.map.tasks.speculative.execution false
set mapred.reduce.tasks.speculative.execution false

DEFINE EsStorage org.elasticsearch.hadoop.pig.EsStorage('es.nodes=localhost:9200', 'es.query=?q=*');

/* load all documents from elasticsearch and filter by a stock symbol */
A = LOAD '$INPUT' USING EsStorage() AS (exchange:chararray, stock_symbol:chararray, stock_date:chararray, stock_price_open:double,
                stock_price_high:double, stock_price_low:double, stock_price_close:double, stock_volume:double, stock_price_adj_close:double);
B = FILTER A BY stock_symbol == '$SYMBOL';
DUMP B;

Örnek kodumuzda borsa bilgilerini yükleyip içerisinden sadece istediğimiz sembole sahip kayıtları getiriyoruz. Bu entegrasyon sayesinde örneğin HDFS üzerindeki verileri, ElasticSearch üzerindeki verileri ve örneğin MongoDB üzerindeki verileri join’leyebilme ve her türlü analiz etme imkanımız oluyor.

Kaynak: http://www.elasticsearch.org/guide/en/elasticsearch/hadoop/current/pig.html

Cloudera Apache Hadoop Geliştirici eğitimini başarıyla gerçekleştirdi

3Dilişim 6-9 Mayıs 2014 tarihlerinde İstanbul’da Cloudera Apache Hadoop Geliştirici eğitimini başarıyla gerçekleştirdi. Eğitim CCDH (Cloudera Certified Developer for Apache Hadoop) sertifikalı İsmail Keskin tarafından verildi. Eğitim sırasında aşağıdaki konular uygulamalı olarak işlendi:

  • Hadoop’un çekirdek teknolojileri HDFS ve MapReduce’un işleyişleri ve MapReduce kodu yazımı
  • Hadoop geliştirmek, hata ayıklamak ve iş akışı ve yaygın algoritmaların gerçekleştirilmesi için en iyi pratikler
  • Hive, Pig, Sqoop, Flume, Oozie, Mahout ve diğer Hadoop ekosistem projelerinden faydalanmak
  • Hadoop kümesini veri merkezine entegre etmek için en uygun donanım ve ağ yapılandırması
  • Veri setlerini birleştirme için MapReduce’da join operasyonu yazma ve yürütme
  • Gerçek-dünya veri analizi için gereken ileri Hadoop API konuları

Daha önce de İstanbul’da yine Cloudera eğitimleri düzenlenmişti ancak eğitimler yabancı bir firma tarafından verilmişti. Cloudera’nın resmi eğitimini Türkçe olarak yetkilisinden alma şansına sahip olmamız güzel bir gelişme.

Ayrıca yine İstanbul’da 24-28 Haziran tarihlerinde Cloudera Apache Hadoop Administrator Eğitimi düzenlenecek. Detaylara buradan ulaşabilirsiniz.

 

Büyük Veri İçerisinde Benzer Öğeleri Bulmak

Benzer Öğeleri Bulmak

Büyük veri içindeki benzer öğeleri bulma, sıkça karşılaşılan ve çözülmesi kolay olmayan bir problem dizisi yaratmaktadır. Birbirine benzeyen bazı çözüm yolları içinden, biz bu yazıda çoğunlukla Mining of Massive Datasets [1] kitabının üçüncü bölümünde anlatılan çözümü temel alacağız. Bu çözümü anlamaya çalışan okuyucunun karşısına iki zorluk çıkmaktadır. Birincisi, çözüm temel olasılık, küme teorisi ve matris bilgisi gerektirdiğinden, bu konulara uzak olan ya da uzak kalmış kişiler için sıkıntı oluşturabilir. İkincisi, algoritma birden fazla alt algoritmadan oluşmakta ve bu algoritmaların birbiri ile olan ilişkisi çözümün anlaşılmasını zorlaştırmaktadır. Bu nedenle çözümü anlatırken, bu zorlukları aşmak adına araya bazı ek bilgiler girecek ve örneklemeler vereceğim. Umarım bu zor konuyu, daha anlaşılır yapabilirim.

 

Problemin tanımı

Büyük verilerin işlenmesi konusu kapsamında bakıldığında benzer öğeleri bulma problemi iki ana alt grupta toplanır. Bunlar benzerliğin;

  • Kümelerin kesişimi problemine dönüştürülebildiği problemler,
  • Kümelerin kesişimi problemine dönüştürülemediği ve herhangi bir uzayda uzaklık ölçme teorisinin kullanıldığı problemler.

İkinci bahsettiğimiz problemlere bir örnek, kısıtlama ve kontrol olmayan bir ara yüz vasıtası ile serbestçe girilmiş adres alanının çözümlenip diğer adresler ile karşılaştırılması probleminde karşımıza çıkar. Bu durumda yazım yanlışları ve kısaltmalar çokça yapıldığı için, kelimelerin üzerinde tanımlanan çok boyutlu bir uzayda, kelimelerin birbirine yakınlığı için bir metrik, uzaklık fonksiyonu tanımlanır. Bu şekilde ‘Hakn Caddsi’ yazıldığında ‘Hakan Caddesi’ olduğu ortaya çıkarılabilir. Bu fonksiyonlara klasik bir örnek Düzenleme Uzaklığı (ing. Edit Distance) fonksiyonudur. Bu konuyu ileride ayrı bir yazıda ele almayı düşünüyorum.

Bu yazımızda birinci kategorideki, kümelerin kesişimi problemine dönüştürülebilenler ile ilgileneceğiz.

 

Kümelerin kesişimi problemine dönüştürmek

Kümelere dönüştürme işlemi yapılabilen bu kategorideki problemler de ikiye ayrılmaktadır. Bunlar;

  • Metin olarak birbirine benzeyen dokümanların bulunması
  • Web’de birbirine benzeyen sayfaları bulma,
  • İzinsiz kopyaların bulunması,
  • Aynaların (ing. mirrors) bulunması,
  • Benzer haberlerin bulunması vb.
  • İşbirliği filtreleri (ing. Collaborative Filtering)
  • Benzer müşterilerin bulunması,
  • Benzer ürünlerin bulunması vb.

Bu problemlerin birbirine benzemesi nasıl olabilir? Anahtar kavram, benzerliklerin ele alınış tarzı ile ilişkilidir. Elimizdeki problemi, kümelerin kesişimi olarak ele almanın yöntemini, yukarıdaki örneklerden birbirine benzeyen dokümanları bulma problemine uygulayarak göstereceğiz.

Herhangi şeylerin tekrarsız olarak bir arada bulunabildiği yapı olarak kümeyi tanımlayalım. Dokümanı bir küme olarak göstermek için dokümanda geçen kelimeleri, birer eleman olarak bu kümeye dahil edelim. Bu durumda, her bir doküman bir küme ile temsil edilmiş olur ve dokümanların birbirine benzerliğini kümeler teorisinin temel işlemleri olan kesişim ve birleşim ile ifade edelim. Kesişim iki kümenin ortak elemanlarını bulma, birleşim ise iki kümenin bütün elemanlarını tekrarlar olmaksızın bir kümede toplama işlemidir.

 

Tanım : Benzerliği, A ve B ismindeki iki kümenin kesişiminin, aynı kümelerin birleşimine oranı olarak tanımlayalım. | A | ile A kümesinin eleman sayısını gösterelim. Bu durumda

 

Benzerlik(A, B) = |AB| / |A U B|

 

A ve B aynı kümeler ise benzerlik değeri 1.0, kesişimleri olmayan ve sembol olarak Ø ile gösterilen iki küme ise benzerlik değeri 0.0 olur. Hemen fark edilebileceği üzere, bu yaklaşımın önemli bir zayıflığı vardır.

 

Şimdi bunu 17 Nisan tarihli bir gazete haberinden [4] aldığımız ve Merkez Bankası Başkanı Erdem Başçı ya ait olduğu söylenen şu cümleye uygulayalım.

 

1.cümle

“ … gelişmekte olan ülkelerde tasarrufların düştüğünü, borçlanmanın arttığını, özellikle gelişmekte olan 5 büyük ülkede cari açık verildiğini söyledi.”

Yöntemdeki zayıflığı göstermek için, bu cümleyi biraz farklılaştıralım.

 

2.cümle

“ … gelişmekte olan ülkelerde tasarrufların arttığını, borçlanmanın düştüğünü, özellikle gelişmekte olan 5 büyük ülkede cari fazla verildiğini söyledi.”

Bu cümlelerden oluşan dokümanlarımızda tekrarlanan kelimeleri attığımızda elimize geçen kümeler,

 

A = { gelişmekte, olan, ülkelerde, tasarrufların, düştüğünü, borçlanmanın, arttığını, özellikle, 5, büyük, ülkede, cari, açık, verildiğini, söyledi }

 

B = { gelişmekte, olan, ülkelerde, tasarrufların, arttığını, borçlanmanın, düştüğünü, özellikle, 5, büyük, ülkede, cari, fazla, verildiğini, söyledi }

 

Benzerlik(A, B) = 14 / 16 = 0,88

 

Birbirine benzer gibi görünen, fakat anlam olarak farklılık taşıyan birinci ve ikinci cümlenin değerlendirilmesi için 0,88 değerini beklediğimizden yüksek bir benzerlik oranı olarak değerlendirebiliriz. Sıkıntı, kümenin elemanlarını oluşturan kelimelerin sırasının kaybedilmesi ile oluşuyor. Bu zayıflığın giderilmesi için öne çıkan yöntem, kümenin elemanları içine bu sıralamanın katılmasını sağlayan özel bir tekniğe dayanıyor.

 

Shingling

Bir metin içinde geçen karakterlerin, her bir alt grup kendinden önceki alt gruptan bir veya daha fazla karakter veya kelime bulunduracak şekilde bölümlendirilmesine shingling adı verilmektedir. Bu şekilde ortaya çıkan her bir alt grup hesaplamalı linguistik de n-gram [2], büyük veri literatüründe ise shingle olarak isimlendirilir. Shingle kelimesinin, yapılarda çatı katlarına uygulanan bir kaplama tekniğinden [3] esinlenilerek, bu tekniğe verildiğini düşünenlere katılmamak elde değil.

Bu tekniğe göre, her bir shingle için bir boyut ve mehter alayının ilerlerken iki adım ileri, bir adım geri gitmesine benzer olarak, her ileri gidişte kaç adım geri gelineceği belirleniyor. Boy için karakter bazlı gidilebileceği gibi, kelime bazlı da gidilebilir. Kelime bazlı işleyişe örnek olarak, k = 2 shingle boyu ve 1 de geri gelme sayısı olmak üzere, yukarıdaki kümeleri şu şekilde ifade edebiliriz.

 

A kümesi B kümesi
“ … gelişmekte olan ülkelerde tasarrufların düştüğünü, borçlanmanın arttığını, özellikle gelişmekte olan 5 büyük ülkede cari açık verildiğini söyledi.” “ … gelişmekte olan ülkelerde tasarrufların arttığını, borçlanmanın düştüğünü, özellikle gelişmekte olan 5 büyük ülkede cari fazla verildiğini söyledi.” 
gelişmekte olanolan ülkelerdeülkelerde tasarruflarıntasarrufların düştüğünü

düştüğünü borçlanmanın

borçlanmanın arttığını

arttığını özellikle

özellikle gelişmekte

olan 5

5 büyük

büyük ülkede

ülkede cari

cari açık

açık verildiğini

verildiğini söyledi

gelişmekte olanolan ülkelerdeülkelerde tasarruflarıntasarrufların arttığını

arttığını borçlanmanın

borçlanmanın düştüğünü

düştüğünü özellikle

özellikle gelişmekte

olan 5

5 büyük

büyük ülkede

ülkede cari

cari fazla

fazla verildiğini

verildiğini söyledi

6 farklı shingle, toplam 15 6 farklı shingle, toplam 15
Benzerlik = 9 / 21 = 0,43

şeklinde küme elemanları haline getirilir. Bu iki cümlenin birbirine benzerliği ilk yöntem ile bulunan 0,88 e göre gerçeğe daha uygun olarak 0,43 e düşer.

Bu işlemden sonra, elemanları 2 kelimeden oluşan katarları içeren ve her biri bir dokümana karşılık gelen kümeler ortaya çıkmış olur. Bu şekilde tanımlanmış olan benzerlik ölçüsüne, ilk ortaya atan kişi olan Paul Jaccard’dan dolayı Jaccard Indeksi ismi verilmiştir [5].

 

Benzer “Benzerlik Problemleri”

  • “benzer müşterilerin bulunması” problemi; müşteriler kümeleri, müşterinin araştırılan davranışını ifade edenler (örnek: satın aldıkları ürünler) bu kümelerin elemanları olarak modellenebilir. Bu durumda yüksek Jaccard indeksine sahip olan müşterileri, birbirine benzer zevkleri, alışkanlıkları olan müşteriler olarak ele alabiliriz.
  • “Benzer ürünlerin bulunması” problemi; ürünler kümeleri, müşteriler bu kümelerin elemanlarını ifade edecek şekilde kurgulanabilir. Buradan yola çıkılarak, iki ürün, satın alan müşterileri ifade eden küme elemanlarının karşılaştırılması sonucu, yüksek Jaccard indeksine sahip iseler benzer ürün veya ilişkili ürünler olarak nitelendirilebilirler.

Her problemde hesaplanan değerin değerlendirilmesinde kullanılacak eşik değeri, probleme özgü olarak belirlenmelidir.

 

Bellek kullanımı

Shingling işlemi doğruluğu arttırmakta fakat bir maliyet çıkarmaktadır. İşlem sonrası her bir doküman bellekte çok daha fazla yer tutar ve işleme zamanı da şüphesiz buna bağlı olarak artar.

Kümeleri temsil eden veri yapılarının, bellekte kaplayacağı alanın büyüklüğünün, doküman sayısına ve dokümanların boyutuna bağlı olacağı açıktır. Her bir küme, N dokümandaki karakter sayısı, k ise shingle sayısı olmak üzere N – ( k – 1 ) adet küme elemanı içerir. Örnek olarak, yaklaşık her birinin ortalama 3000 karakter içermesi ve k = 5 seçilmesi durumunda 3000 – ( 5 – 1 ) = 2996 tane elemanı olan küme karşılık gelir. Küme sayısının artması bellek kullanımını ciddi bir miktarda arttıracaktır.

Shingle seçerken karakter değilde, kelime üzerinden gidilecek olunursa, her bir küme elemanının ortalama 30 byte lık bir alan kapladığı varsayımı altında, 100.000 doküman/küme olduğu bir durumda 100.000 x 2996 x 30 = 8.4 GB bir alan sadece küme elemanları için kullanılması gerekmektedir.

 

Alt Problem : Kullanılan bellek miktarının çokluğu

Doküman sayısının dolayısı ile karşılık gelen küme ve içindeki elemanların sayılarının artması ile bu rakamın çok üzerine çıkılacağı açıktır. Bu nedenle, kümeleri hem yer probleminin önüne geçmek, hem de sonuçta her bir kümenin diğerleri ile karşılaştırılması sırasında gerekecek işlem zamanını azaltmak için, akıllıca bir çözüm bulmak zorunluluğu ortadadır. Bu çözüm paralel işlem yapma olanağı da vermelidir ki, kısa zamanda sonuca ulaşmak mümkün olsun.

Her bir küme elemanının daha küçük bir alanda gösterimini sağlamak için, yazılım algoritmalarında çokça kullanılan Hashing fonksiyonlarından [6] faydalanmak uygun bir çözümdür. Bu sayede değişik boyutlarda, yerine göre onlarca byte olan her bir elemanı, bellekte sabit bir alan kaplayan bir sayıya çevirmek mümkündür. Bu işlem ile tekrarlardan da kurtulmak kolaylaşmış olmaktadır. Aynı eleman hep aynı hash değerini alacaktır.

Bunun için her bir elemana hashing fonksiyonu uygulanarak bir makine komutu ile işlenebilen hale getirmek faydalıdır. Bu algoritmanın üzerinde çalışacağı makinanın 32 bit veya 64 bit olmasına göre 4 veya 8 byte lık bir gösterim alanı anlamına gelmektedir. Bu şekilde iki elemanın karşılaştırılması işlemi, uzun ve karmaşık katar fonksiyonları kullanmak yerine, tek bir sayı karşılaştırma işlemi ile yapılabilir hale gelir.

 

Kümelerin Benzerliğinin Korunduğu Özetler

Hashing fonksiyonları kullanarak elemanların kapladığı alanı küçültmek faydalıdır ama büyük veri ile çalışıyorsanız, bu bile yeterli gelmeyebilir. Bu durumda karşılaştırma için kullandığımız kümeleri daha da küçük bir alan kaplayacak şekilde bir gösterim yolu bulabilir miyiz?

 

Matris Gösterimi

Bellekte kullanılan alan optimizasyonu için matrislerden yararlanacağız. Sütunları kümeler, satırları ise evrensel küme elemanları olan bir matris kurgulayalım. Evrensel küme bütün kümeleri içinde barındıran küme olarak tanımlansın. Buradan itibaren hesaplamaları ve gösterimleri yer kısıtımızı da gözeterek kolaylık açısından şöyle gösterelim. Dokümanların shingling yapılmış ve karşılık gelen elemanlarına hash fonksiyonu uygulanmış hallerini a, b, c, d, e ile gösterelim.

 

Evrensel Küme E ={a,b,c,d,e}

 

Alt kümeler, yani dokümanlarımız;

S1={a,d}

S2={c}

S3={b,d,e}

S4={a,c,d}

 

İki boyutlu matrisler genel olarak dokümanlarda sıkça kullandığımız tablolara benzerler, üst satırdakiler matris sütun indeksi, sol tarafta bulunan sütundakiler ise satır indeksi olarak ele alınırlar. Her hangi bir eleman örnek olarak (1,2) yani ilk satırın ikinci elemanı olarak gösterilebilir. Buna göre yukarıdaki kümeler matris olarak, aşağıdaki matris ile gösterilebilir ve bu matriste (1,2) elemanı (a, S2) elemanı anlamına gelir ve değeri 0 dır.

 

S1 S2 S3 S4
a 1 0 0 1
b 0 0 1 0
c 0 1 0 1
d 1 0 1 1
e 0 0 1 0

 

Bu matris, sıfırdan farklı elemanlarının sayısının, elemanların sayısının yarısından çok olması nedeni ile literatürde seyrek (ing. Spare) matris olarak isimlendirilir. Seyrek matrisler, hem bellekten kazanmak hem de işlemler sırasında avantaj sağladığı için, bellekte tutulurken matris yapısında değil, sadece sıfırdan farklı elemanların dikkate alındığı tuple yapısında tutulur. Tuple değerlerin sırasının önemli olduğu bir çeşit liste yapısıdır. Yukarıdaki matrisin ilk satırı şu şekilde gösterilebilir.

 

( ((a,S1), 1), ((a,S4), 1) ) veya (a,((S1, 1), (S4, 1)) )

 

Minhashing

Yukarıdaki matris üzerinden Jaccard Benzerlik fonksiyonu ile kümelerin ikili benzerlikleri kolayca hesaplanabilir. Fakat eleman sayısı arttıkça bellek ihtiyacı da artar. Amacımız belleği en az kullanarak bu hesabı yapmak olunca, şu ipucu ile bir yöntem geliştirebiliriz. Matristeki her bir kolona yani kümeye uygulanabilen öyle bir h fonksiyonu bulalım ki bu amacımıza ulaşabilelim.

 

Bunun için bu fonksiyon iki özelliği gerçeklesin.

  • Bellekte tutulabilecek şekilde her bir S için küçük bir imza yaratabilelim.
  • Benzerlik(Si, Sj) ile, h(Si) ve h(Sj) imzalarının benzerliği eşit olsun.

 

Bu iki koşulu birleştirelim ve öyle bir h fonksiyonu bulalım ki,

  • Benzerlik(Si, Sj) yüksek ise, yüksek olasılıkla h(Si) = h(Sj) olsun.
  • Benzerlik(Si, Sj) düşük ise, yüksek olasılıkla h(Si) ≠ h(Sj) olsun.

 

Bu durumda hash fonksiyonu kullanarak dokümanları her biri bir sayıya karşılık gelen kovalara koyalım ve birbirine benzer doküman ikililerinin çoğunlukla aynı kovalara konmasını bekleyelim.

Bunu sağlayan bir hash fonksiyonu Minhash olarak bilinir ve aşağıdaki şekilde tanımlanır.

 

Minhash Fonksiyonu

Tanım : π,E kümesi üzerinde alınan herhangi bir permütasyon olsun. Yukarıdaki matriste S kümesinin bu permütasyon sırasına göre 1 değerini aldığı ilk elemanın sıra değeri bu kümenin minhash değeri olarak nitelendirilir ve matematiksel olarak

 

hπ(S) = min π(S)

 

olarak gösterilir. Bu şekilde söylenince karışık gelmiş olabilir, bunu daha anlaşılır bir şekilde ifade edelim.

 

Açıklaması :

Minhash işlemi, yukarıdaki matris üzerinden gidecek olursak, ilk kolondaki elemanların herhangi bir permütasyonunun [7] alınması ile başlar. Permütasyon almayı, konu bağlamında kısaca, kümenin elemanlarını bir torbada toplayıp her defasında bir adet elemanı rastgele torbadan çekmek ve bunu iadesiz olarak bütün elemanlar bitene kadar yapmak, bu işlem sırasında çekme sırasını not almak olarak tarif edebiliriz. Bu şekilde torbada eleman kalmayınca olası permütasyonlardan biri yani π alınmış olur. İstendiği sayıda permütasyon için işlem tekrarlanır.

Permütasyon alındıktan sonra, permütasyon sırasına göre yani torbadan çekme sırasına göre her bir kolonda ilk 1 değerine karşılık gelen eleman, o kolonun Minhash değeri olarak isimlendirilir.

Örnek olarak, E kümesinin bir permütasyonu yani dizilişi π = { b, e, a, d, c } olarak alınabilir. h minhash fonksiyonunu göstermek üzere h(S1) → a değerine karşılık gelen sıra yani h(S1)=3 olur. Burada yapılan, sırası ile b değeri, e değeri, ve a değerinin S1 kolonunda 1 e karşılık gelip gelmemesine bakmak, b ve e için 0 olduğundan geçmek, a için 1 olduğundan orada durmaktır. Benzer şekilde h(S2)=5 e karşılık gelir.

Tabii burada bütün elemanların tutulması ve gerekirse her birine bakılması gerektiği görülmektedir. Acaba benzerlik değerini belli bir hata payını göze alarak sadece elemanların bazılarına bakarak bulabilir miyiz? Bu şekilde hem işlem sayısı açısından, hem de kullanılan bellek miktarı açısından önemli bir kazanım sağlamamız mümkün olabilecektir.

 

MinHash İmzaları

Yukarıdaki şekilde bir matrisimiz olsun ve M olarak isimlendirelim. Kümeleri daha az bellek birimini kaplayacak şekilde temsil etmek için, M nin satırlarının n tane permütasyonunu üretelim. Duruma göre, 100 veya yüzlerce sayıda üretilebilir. Bu permütasyonlar ile belirlenen minhash fonksiyonlarını h1,h2, … , hn ile gösterelim. Bu durumda S sütununun minhash imzasını [ h1(S),h2(S), … , hn(S) ] vektörü ile gösterebiliriz. M matrisinin ilgili kolonunun minhash imzası ile oluşturulan her bir vektörü, M matrisinde kendi sütununun bulunduğu yere koyarak imzalardan oluşan bir M matrisi elde ederiz. Dikkat edilirse burada imza matrisi, M ile aynı sayıda kolondan oluşuyor ama satır sayısı n ile sınırlıdır. Bu şekilde çok sayıda elemanı olan bir dokümanı yani kümeyi az sayıda eleman ile temsil etmiş oluruz. Dolayısı ile imza matrisimiz, asıl M matrisi ile karşılaştırıldığında oldukça küçük bir alanı kaplar.

 

Minhash İmzalarının Bulunması

Yukarıda anlatılan algoritma ile Minhash imzaları hesaplansa da, çok büyük M matrisleri için yine de uygulanabilir değildir. Bu nedenle pratikte uygulanabilir bir algoritmaya ihtiyaç vardır. Rastgele permütasyonun etkisini öyle bir hash fonksiyonu seçerek simüle edebiliriz ki, her bir satır numarasına karşılık satır sayısı kadar hash kovası içinden bir kova denk gelsin. Bu aşamada dikkat edilecek nokta, klasik Hash fonksiyonlarının aynı kovada birden fazla eleman düşürmesi normal ve beklenen özelliği olmasına karşın, burada seçeceğimiz hash fonksiyonlarının her bir kovaya mümkün olduğunca tek eleman düşecek şekilde seçilmesidir.

Bu nedenle satırların n defa rasgele permütasyonunu almak yerine, n tane rasgele seçilmiş hash fonksiyonu h1,h2, … , hn yi ilgili satırlar üzerinde hesaplıyoruz. Örnek olarak x + 1 mod 5 yukarıdaki matris için bu şekilde bir hash fonksiyonudur.

 

Satır numarası H1 = x + 1 mod 5 H2 = 3 x + 1 mod 5
0 1 1
1 2 4
2 3 2
3 4 0
4 0 3

 

Bu hash fonksiyonlarını kullanarak M nin imzası olan göreceli küçük matrisi elde edebiliriz. Başlangıç olarak sütunlar kümeleri, satırlar seçtiğimiz fonksiyonları göstersin. Matrisin her bir elemanının başlangıç değeri olabilecek en büyük değer olarak ∞ yani sonsuz seçilir.

 

S1 S2 S3 S4
h1
h2

 

Algoritma her bir r satırı için şu şekildedir.

  1. Her bir hash fonksiyonu için h1(r),h2(r), … , hn(r) hesaplanır.
  2. Her bir S kolonu için şu işlemler yapılır;
  3. r satırındaki S kolonuna karşılık gelen değer 0 ise herhangi bir şey yapılmaz.
  4. r satırındaki S kolonuna karşılık gelen değer 1 ise, sırasıyla i=1,2,…,n değerleri için Benzerlik(i,S) değeri min( Benzerlik(i,S) nin o anki değeri, hi(r) )

Bu algoritma kullanılarak imzayı elde edelim.

Öncelikli olarak h1(0) = 1 ve h2(0) = 1 olduğu görülür. 0 satırındaki değerlere baktığımızda sadece S1 ve S4 e karşılık gelen değerler 1, o halde bu değerlerde değişiklik olabilir.

 

Min(∞, h1(0) = 1) = 1 ve Min(∞, h2(0) = 1) = 1

 

S1 S2 S3 S4
h1 1 1
h2 1 1

 

İkinci satır yani r=1 için h1(1) = 2 ve h2(1) = 4 olduğu görülür. 1 satırındaki değerlere baktığımızda sadece S3 e karşılık gelen değer 1, o halde bu sütundaki değerlerde değişiklik olabilir.

 

Min(∞, h1(1) = 2) = 2 ve Min(∞, h2(1) = 4) = 4

 

S1 S2 S3 S4
h1 1 2 1
h2 1 4 1

 

Bu işlemleri bu şekilde devam ettirdiğimizde üç adım sonra şu matris elde edilir.

S1 S2 S3 S4
h1 1 3 0 1
h2 0 2 0 0

 

Bu imza matrisinden kümelerin Jaccard Benzerlikleri hesaplanabilir. İlk bakışta görüleceği üzere S1 ve S4 kolonları aynıdır yani Benzerlik(S1, S4) = 1.0 dir. İlk matrise baktığımızda Jaccard benzerliğinin 2/3 olduğunu görüyoruz. Buradan, gerçek benzerlik 2/3 e yaklaşım için 2 hash fonksiyonunun az kaldığını, fonksiyon sayılarını arttırdığımızda gerçeğe daha fazla yaklaşacağımızı söyleyebiliriz. Öte yandan Jaccard Benzerlik kestirimi imza matrisinden Benzerlik(S1, S2) = 0 dır ve bu gerçek benzerliktir.

 

Yerel Duyarlı Hashing (LHS)

Belki garip gelecek ama şu ana kadar yaptığımız tüm bu işlem ve çözümler, büyük veri ile çalışırken bazı dokümanların ikili benzerliklerini hesaplamak için yetersiz kalabilir. Bunun nedeni, dokümanların ikili karşılaştırmalarının sayısının çok fazla olabilmesidir. Örnek olarak 1.000.000 dokümanı karşılaştırmak isteyelim. Bu üstel gösterimle 106 edecektir. İmzaların 250 tane olduğunu düşünürsek, her bir dokümanın imzası için 1000 byte kullanılır. Bu durumda ikili kombinasyonlarını yani 106 C 2 yi hesaplarsak yaklaşık

 

1012/2 = 5 x 1011

 

ikili eder. İkili karşılaştırmaların her birinin tahmini 1 mikro saniyede yapıldığını kabul etsek, saniyede 1.000.000 yani 106 karşılaştırma yapılabilir. Bu şartlarda tüm hesaplamaları yapmak 6 gün sürebilir.

Yapılacak işi azaltmadan, paralelliği kullanarak hesaplama zamanını azaltabiliriz fakat istediğimizi yine de elde edememe durumu olabilir. Bu hesaplamayı daha kısa zamanda yapmak için, benzerlikleri her bir ikili için değil de sadece belli bir eşik değerini geçen ikililer için hesaplayamaz mıyız? Evet, bu yönteme Yerele Duyarlı Hashing (ing. Locality Sensitive Hashing – LSH) denmektedir.

Bunun için yaptığımız hash işleminin tekrarlı olarak farklı fonksiyonlarla yapılması, bu tekrarlar sonucunda aynı hash kovasına en az bir kere girenlerin benzer olabileceklerine, girmeyenlerin ise benzemediklerine hükmedebiliriz. Tabii bu yöntem ile belli bir hata yapmayı da kabul etmiş oluyoruz. Yanlış Pozitif hatalar, aynı kovaya girip de benzemeyenler, gereksiz işlem yapmamıza neden olurlar. Doğru Negatifler ise aynı kovaya girmemelerine rağmen benzer olanlardır. Bu algoritma detayı için [1] e bakılabilir.

 

Sonuç

Görüldüğü üzere benzer öğeleri bulma probleminin basit bir çözümü yok. Fakat bu kategorideki mevcut problemleri ve çözüm yöntemlerini anlamak, eldeki probleme özgü sıkıntı noktalarını tespit etmek için ciddi bir olanak sunuyor. Bu şekilde hali hazırda bu algoritmaları kullanan kütüphane veya ürünleri kendi problemimizi çözmek için kullanırken, arka plandaki işleyişin farkında olmanın bize getireceği avantajlardan yararlanabiliriz. Ayrıca, kendi problemlerine özgü çözüm geliştirmek isteyen geliştiricilerin, probleme özel kendi algoritmalarını geliştirmeleri gerektiği durumlarda da faydalı olacaktır.

 

Kaynaklar

[1] http://infolab.stanford.edu/~ullman/mmds.html

[2] http://en.wikipedia.org/wiki/N-gram

[3] http://www.wikihow.com/Lay-Shingles

[4] http://www.sabah.com.tr/Ekonomi/2014/04/17/erdem-bascidan-istifa-iddiasina-aciklama

[5] http://en.wikipedia.org/wiki/Jaccard_index

[6] Hashing, indexing ve Bloom Filtreleme

[7] http://tr.wikipedia.org/wiki/Perm%C3%BCtasyon

 

Büyük Veri İçindeki Nadir Görülen Olayların Keşfedilmesi

Bu yazımızda, veri madenciliği çalışmalarında sıkça karşılaşılan “büyük miktarda veri içinde nadir görülen olayların keşfedilmesi” problemlerini çözerken dikkat etmemiz gereken önemli bir konuyu ele alacağız. İstatistik literatüründe çoklu karşılaştırma problemiçoklu hipotez testi gibi isimlerle anılan bu problemler veri madenciliği alanında aktif araştırma konuları içinde yer almaktadır [1]. Değişik uygulama alanları olmakla birlikte, biz burada bir örnek üzerinden temel problemi anlatmaya çalışacağız.

Büyük veri içinde nadir görülen olayların konu bağlamında incelenmesinin güzel bir örneğini, Devasa Veri Setlerinde Madencilik [2] kitabında görüyoruz. Dünya süper gücü olan bir devletin, bütün dünyayı bir çok veri toplama yöntemi ile sürekli izlediğini varsayalım. Toplanan bu veriler işlenmekte, kişilerin ne yaptığı konusunda veri madenciliği yöntemleri ile otomatik çıkarımlar yapılmakta, çıkan sonuçlar olası tehdit değerlendirmeleri olarak istihbarat servisine aktarılmaktadır.

İstihbarat servisi çıkan bu bilgilere dayanarak elindeki imkanları belirlenen kişileri yakın takibe almak için kullanmaktadır. Böylelikle olası tehditlerin gerçekleşmeden önlenebilmesi için önemli bir kazanım elde edildiği düşünülmektedir.

Bu tarz bir sistemin çalışmasında elimizde büyük veri işleme imkan ve kabiliyetleri var ise nasıl bir çıkarım mekanizması kurulabilir? Bu çıkarım mekanizması bizi gerçekten faydalı bir sonuca götürebilir mi? Yani olası tehditleri gerçekleştirecek kişiler listesine. Yoksa masum insanları şüpheli konumuna düşürme, dolayısı ile hem bu kişileri rahatsız etme, belki de gözetim altına alma, hem de imkanların boş yere harcanması şeklinde istenmeyen bir sonuca varabilir miyiz? Cevap, aradığımız aktivitelerin tanımını ne kadar daralttığımıza bağlıdır. Bunun teorik bir arka planı da vardır.

 

Bonferroni prensibi

Elimizde bir miktar veri var ve bu verinin içinde belli tipteki olayların gerçekleşip gerçekleşmediğini araştırıyoruz. Elimizdeki bu veri tamamen rastgele üretilmiş bir veri olsa bile, aradığımız tipte olayların bu verinin içinde olma olasılığı vardır ve verinin boyutu büyüdükçe aradığımız tipte olayların bu verinin içinde bulunma sayılarının artmasını beklemek yanlış olmaz. Bu şekilde tespit edilen gerçeklemeler teknik olarak aldatmaca olarak nitelendirilir ve bazı az rastlanan özelliklerin önemli olarak gözükebileceği, fakat tamamen rastgele olan verilerde bu tip durumların şans eseri olabileceği düşüncesi ile önemsiz olduğu kabul edilir. İstatistikte Bonferroni düzeltmesi olarak geçen teorem kullanılarak, buradaki aldatmacalı pozitif dönüşlerin önemli bir kısmından kurtulmak mümkündür. Yani veri içindeki rastgele oluşmuş bulunan olayların gerçek olaylarmış gibi ele alınmasına engel olacak bir yöntemden bahsediyoruz.

Bunun için, verinin rastgele olduğu kabulü altında, araştırdığımız olayların beklenen vuku bulma sayıları hesaplanır. Eğer bu sayı gerçek veri içinde bulunmasını beklediğiniz sayıdan ciddi bir manada büyükse, bu durumda bulduğumuz her şeyin önemli bir kısmının aldatıcı olduğunu düşünebiliriz. Bu yorum Bonferroni prensibi olarak anılan yöntemin özünü oluşturmaktadır.

Kötü niyetli kişiler listesine geri dönecek olursak, herhangi bir zamanda çok az sayıda kötü niyetli kişi olmasını bekleyebiliriz. Bonferroni prensibi bize bu kişileri bulmanın çok nadir görülen ve rastgele verinin içinde olması adeta beklenmeyen olaylara dayandırılması gerektiğini söyler.

 

Uygulama örneği

Varsayalım ki gerçekten az sayıda niyetleri kötü olan kişiler var ve biz bu kişileri tespit etmek istiyoruz. Yine varsayalım ki, bu kişiler kötü niyetlerine erişmek amacı ile düzenli olarak bir otelde toplanıp kararlar alıyorlar. Problemin boyutunu belirlemek için; şu kabulleri yapalım.

Kabullerimiz

  • Muhtemel kötü kişiler bir milyar insan arasından çıkabilir.
  • Herkes 100 günde bir otele gider.
  • Her bir otel ortalama 100 kişiyi ağırlayabilir diye kabul edelim. Dolayısı ile 1 milyar kişinin %1 ini herhangi bir gün ağırlamak için 100,000 otelin var olduğunu kabul ediyoruz.
  • Oteller kayıtlarını 1000 günlük geçmişi tutacak şekilde saklıyor ve bu kayıtlara erişebiliyoruz.

Veri içinde aradığımız örüntüyü, iki farklı gün aynı otelde kalan insanlar olarak tanımlıyoruz.

Karşılaşabileceğimiz olası bir durum, gerçekte elimizdeki verinin içinde hiç kötü niyetli kişi olmamasıdır. Yani herkes tamamen rastgele davranarak 0.01 olasılıkla herhangi bir gün 105 otel içinden bir oteli rastgele seçerek ziyaret edebilir.

Eldeki büyük veride hiç kötü niyetli kişiler olmasa bile, veri madenciliği çalışması sonucu, şüpheli kişilerin bulunduğu söylenebilir mi? Basit hesaplamalar yaparak yukarıda yaptığımız kabuller altında bu soruyu cevaplamaya çalışalım.

 

Hesaplamalar

Herhangi iki kişinin aynı gün bir oteli ziyaret etme olasılığı 0.0001 dir. Bu otelin aynı otel olma olasılığı ise bu olasılığın otel sayısına yani 105 e bölümü ile çıkan sayıdır. Bu durumda bu iki kişinin aynı oteli aynı gün ziyaret etme olasılığı 10-9 dur. Bunun iki kere tekrar etme olasılığı ise 10-18 dir.

Şimdi kaç olayın tanımladığımız örüntü kapsamında kötü niyetli olay kapsamına girebileceğini hesaplayalım. Bu kapsamda olayı, iki farklı kişinin, aynı iki günde, aynı otellerde olması olarak ele alalım. Hesaplamalarda basitlik sağlamak için, n popülasyondaki kişi sayısı olmak üzere binom katsayılardan bildiğimiz üzere nC2 ( yani n nin 2 li kombinasyonları) sayısı büyük n değerleri için asimptotik formülasyondan [3]

nC2 ≤ n2 / 2!

olduğundan n2 / 2 olarak alacağız. Bu yaklaşık değeri alarak hesaplamalarımızı yapacak olursak;

Herhangi iki kişi sayısı yaklaşık 109C2 = 5 x 1017 = K

Herhangi iki gün sayısı yaklaşık 103C2 = 5 x 105 = G

Örüntü = Herhangi iki kişi ve herhangi iki günün aradığımız davranışın bir örneği olma ihtimali

ham P-değeri = 10-18

Belirlediğimiz olay tipinin gerçeklenme beklenen değeri = K x G x (ham P-değeri)

m örüntü sayısı olmak üzere,

m = 5×1017 ×5×105 ×10-18 = 250,000

elimizdeki veride istatistiksel olarak anlamlı olmasını beklediğimiz örüntü sayısını verir.

 

Sonuçların Yorumlanması

Kötü niyetli kişiler olmamasına rağmen elimizdeki veriden 250,000 kişilik bir olası kötüler listesi çıkarmış olduk. Bu uygulanabilir bir sonuç da çıkarmadı aynı zamanda. 10 kişi olsaydı bile bu 250,000 kişi arasından bu 10 kişiyi bulmak pratik olarak imkansız olacaktır.

Bu sayı başta belirlediğimiz popülasyon olan 1 milyar kişi içinde olası olan 5 x 1017 tane ikili dikkate alındığında yüzde olarak 5 x 10-13 ü oluyor.  α = 0.05 olarak seçildiğinde 250,000 sayısı bütün mümkün ikilileri gösteriyor anlamına geliyor.

 

Bonferroni düzeltmesi

Oysaki Bonferroni düzeltmesini uyguladığımızda α= α / 5 x 1017 = 10-19 olarak bulunur. Yani, çıkan p değeri 5 x 10-13 < 10-19 şartı sağlanmadığından istatistiksel olarak çıkan ikililerin anlamlı olmadığı sonucunu çıkarabiliriz. Bu şekilde veri madenciliği sonuçlarına göre yanlış pozitif olarak değerlendirilen kişilere karşı yapılacak gereksiz işlemlerin önüne geçmiş oluyoruz.

 

İyileştirme

Aldığımız sonuca göre başta aldığımız örüntü tanımlarını daha fazla daraltmak gerektiğine hükmedebiliriz. Bu daraltma, örneğin aynı otelde iki gün kalma şartını üç güne çıkartarak yapılabilir.

Bu örnek çerçevesinde görüldüğü üzere, büyük veri ile çalışırken eldeki verinin işlenmesinde klasik yöntemlerin kullanılması sırasında istenmeyen durumlar oluşabilir. Bu durumlar kurum ve şirketlerde bazen etkisi hissedilmeyen, bazen de etkisi para, zaman veya prestij kaybına yol açabilen şekillerde de hissedilebilen kararların alınmasına yol açabilir [4].

 

Kaynaklar

[1] Multiple Hypothesis Testing in Data Mining, Doctoral Dissertation, Sami Hanhijarvi, Department of Information and Computer Science, Aalto University, Finland, 2012.

[2] Mining of Massive Datasets, A. Rajaraman, J. Leskovec, J. D. Ullman, p. 5, 2014

[3] http://en.wikipedia.org/wiki/Binomial_coefficient#Bounds_and_asymptotic_formulas

[4] http://bytesizebio.net/2010/10/27/but-did-you-correct-your-results-using-a-dead-salmon/

 

 

 

 

Apache Solr ile Otomatik Tamamlama

solrBu yazımızda Apache Solr kullanılarak otomatik tamamla ( bazen tavsiye olarak da isimlendiriliyor) nasıl yapılır onu anlatacağım.

Bu örneği olabildiğince genel hazırlamak için solr dağıtımını indirdiğimizde içinden çıkan varsayılan örnek üzerine inşa edeceğiz. java –jar start.jar ile çalıştırdığımız.

Schema.xml‘e yapılacak eklentiler:

İki tane yeni alan ve tip ekleyelim ve bu alanları copyField ile dolduralım.

<field name="subject_edgy_keyword" type="edgy_keyword" indexed="true" stored="false"/>
<field name="subject_edgy_ws" type="edgy_ws" indexed="true" stored="false"/>

<copyField source="subject" dest="subject_edgy_keyword"/>
<copyField source="subject" dest="subject_edgy_ws"/>

<fieldType name="edgy_keyword" class="solr.TextField" positionIncrementGap="100">
  <analyzer type="index">
    <tokenizer class="solr.KeywordTokenizerFactory" />
    <filter class="solr.TrimFilterFactory" />
    <filter class="solr.LowerCaseFilterFactory" />
    <filter class="solr.EdgeNGramFilterFactory" minGramSize="1" maxGramSize="20" />
  </analyzer>
  <analyzer type="query">
    <tokenizer class="solr.KeywordTokenizerFactory" />
    <filter class="solr.LowerCaseFilterFactory" />
  </analyzer>
</fieldType>

<fieldType name="edgy_ws" class="solr.TextField" positionIncrementGap="100">
  <analyzer type="index">
    <tokenizer class="solr.WhitespaceTokenizerFactory" />
    <filter class="solr.LowerCaseFilterFactory" />
    <filter class="solr.EdgeNGramFilterFactory" minGramSize="1" maxGramSize="20" />
  </analyzer>
  <analyzer type="query">
    <tokenizer class="solr.WhitespaceTokenizerFactory" />
    <filter class="solr.LowerCaseFilterFactory" />
  </analyzer>
</fieldType>

Solrconfig.xml‘e yapılacak eklentiler: aşağıda gösterildiği tamamla isimli bir request handler kaydediyoruz.

<requestHandler name="/tamamla" default="false">
  <lst name="defaults">
    <str name="defType">dismax</str>
    <str name="echoParams">none</str>
    <str name="omitHeader">true</str>
    <float name="tie">0.01</float>
    <str name="qf">subject_edgy_ws^8 subject_edgy_keyword^4</str>
    <str name="pf">subject_edgy_ws^2 subject_edgy_keyword^20</str>
    <str name="fl">subject</str>
    <int name="ps">0</int>
    <int name="qs">0</int>
    <str name="q.alt">*:*</str>
    <str name="mm">100%</str>
    <str name="version">2.2</str>
    <int name="rows">10</int>
    <int name="start">0</int>
  </lst>
  <arr name="components">
    <str>query</str>
  </arr>
</requestHandler>

Veri: Umuma açık bulunan MovieLens 10M verisini kullanacağız. ml-10m.zip dosyasını indirebilirsiniz.

Bu sıkıştırılmış klasörü açtığımızda içinden çıkan dosyalardan bize lazım olanı movies.dat dosyası. Bu dosyayı solr’a gönderebilmemiz için ufak bir iki değişiklik yapacağız. İndirdiğimiz dosyanın orijinal içeriği (10K satır) şu şekilde olacak:

solr1

Bu değişiklikler bir metin editöründe bul-ve değiştir işlemi olacak. Notepad++, TextWrangler gibi bir programla açıp şu iki işlemi sırasıyla yapalım:

1) Bütün | karakterlerini boşluk ile değiştirelim.

2) Bütün :: karakterlerini | ile değiştirelim.

solr03

Dosyayı bu hali ile kaydedelim. Artık elimizde solr’a doğrudan beslenebilecek formatta getirdik. Curl programı ile bu dosyayı aşağıdaki komut ile indexleyelim:

curl "http://localhost:8983/solr/update?commit=true&fieldnames=id,subject,&separator=|&encapsulator=/" --data-binary @movies.dat -H 'Content-type:application/csv; charset=utf-8'

İşlemin sonunda söyle bir mesaj almamız lazım her şey yolunda gittiyse :

<?xml version="1.0" encoding="UTF-8"?>
<response>
  <lst name="responseHeader">
    <int name="status">0</int>
    <int name="QTime">2404</int>
  </lst>
</response>

Not: Windows işletim sistemlerinde curl programı hali hazırda gelmiyor. Ama Windows için sonradan kurmak mümkün. Ama ek kurulum yapmak istemezseniz, solr’un içinden (example/exampledocs dizini altında) post.jar kullanarak indeksleme için aşağıdaki komut satırını kullanabilirsiniz.

java -Durl="http://localhost:8983/solr/update?commit=true&fieldnames=id,subject,&separator=|&encapsulator=/ " -Dtype=text/csv -jar post.jar movies.dat

Her şey yolunda gittiyse, işlem sonunda siyah ekranda şuna benzer bir çıktı alırsınız:

SimplePostTool version 1.5
POSTing file movies.csv
1 files indexed.
COMMITting Solr index changes to ...
Time spent: 0:00:04.649

Arama: Kullanıcı tuşlara bastıkça, her tuşa basma sonunda /tamamla adresine tuşlanmış olan karakter serisini gönderiyoruz. Kullanıcı w tuşuna basmış olsun,
http://localhost:8983/solr/collection1/tamamla?q=w&wt=json&indent=true
gelen ilk üç sonuç şu şekilde olacaktır.

"subject": "Wild Wild West (1999)"
"subject": "What Women Want (2000)"
"subject": "When We Were Kings (1996)"

solr04

Yukardaki resimde (godf sorgusuna) dikkat ettiğiniz gibi ilk kelimesi godfather olanlar üstte, sonrasında ise ilk kelimesi olmadığı halde godfrey geçen film başlıkları da gelmiştir.

sex c sorgusuna ise gelen sonuçlar aşağıdaki gibidir.

http://localhost:8983/solr/collection1/tamamla?q=sex+c&wt=json

solr05

Eğer otomatik tamamlanın sıralamasına dahil etmek istediğiniz başka nümerik alanlarınız varsa onları da edismax’ın boost parametresi ile ekleyebilirsiniz. Örneğin bu örnekte filmlerin izlenme sayıları (view_count) elimizde olsaydı boost=sqrt(view_count) FunctionQuery olarak sıralamaya etki ettirebilirdik. Ya da son iki yılda çıkan filmleri üste getirmek için bq=year:[2013 TO 2014]^50 diye parametre ekleyebilirdik.

Kaynakça:

Auto-Suggest From Popular Queries Using EdgeNGrams

ExtendedDisMax

Different Ways To Make Auto Suggestions With Solr

Super flexible AutoComplete with Solr

Apache Pig – Domuzcuğun Hikayesi


pig-on-elephantApache Pig

Apache Pig, Apache Hadoop üzerinde prosedurel bir data akışı yazmayı sağlayan bir veri işleme platformudur. Veri kullanıcılarına Hadoop’un güçlü, dağıtık ve esnek yapısına ileri seviye java kodları yazmadan daha üst bir katmandan erişim imkanı sağlayan bir yapıdır.

Pig’in iki önemli bileşeninden Pig Latin dilini kullanarak kullanıcılar data akışı scriptleri yazabilirler ve Pig bunları Hadoop üzerinde MapReduce kodlarına çevirerek run eder. Pig’in en büyük getirisi Java bilmeyen kullanıcılara da Hadoop üzerinde üstseviye prosedurel bir script dili ile veriye ulaşma ve işleme imkanı vermesi, Map Reduce programları yazmaya gerek bırakmamasıdır.

Tabi şöyle bir problem veya risk yine buradada olacak; nasıl ki RDBMS üzerinde veri modeli, veri uzmanlığı olmayan kullanıcılar performans problemlerine yol açan anlamsız bazı SQL’ler yazabiliyorsa burada da pig latin scriptleriyle yazılan scriptlerde de benzer bir risk var. Aynen SQL’de olduğu gibi veri konusunda uzman veriyi iyi tanıyan kişilerin kontrolu altında bu data akışlar yazılmalıdır. Kullanıcı nerede hangi veriye hangi join yapacağını iyi bilmelidir.

Bu riski eski Yahoo Pig geliştirme ekibinden Alan Gates Pig’i şöyle tanımlıyor “ “Because… Pig is domestic animal, does whatever you tell it to do.”
Yani “Çünkü…Pig evcil bir hayvandır, ne söylerseniz onu yapar. ”

Pig

Pig, Yahoo bunyesindeki bir geliştirme ekibi tarafından Hadoop üzerinde veri transform ve analiz işlemlerini yazmayı hızlandırmak amacıyla geliştirildi. Alan Gates’de bu ekibin üyelerinden biriydi daha sonra kendisi şu anda Hadoop dünyasının önemli katkı veren şirketlerinden Hortonworks’un kurucularından birisi oldu.

Alan Gates’in O’Reilly’den Pig Programming kitabına ulaşmak için : http://www.gocit.vn/files/Oreilly.Programming.Pig-www.gocit.vn.pdf

Yazılan Pig Latin scripti bir dizi Map ve Reduce işlerine dönüştürülüyor ve Hadoop üzerinde çalıştırılıyor. Pig kodu geliştiricisi yazdığı Pig Latin scriptinin arka tarafta kaç adet MapReduce koduna çevrildiğini, compile edildiğini, paketlenip çalıştırılarak sonuçların getirildiğini farketmiyor. Bunu ancak logdaki ifadelere bakarak anlayabiliyor.

Nerelerde kullanılabilir

ETL (Extract-Transform-Load) işlemlerinde ve özellikle de ETL’in “T”’si Transform işlemlerinde kullanılabilir, tabi klasik RDBMS üzerindeki ETL’den farklı bir bakış gerektirecektir.

Ham Veri üzerindeki bazı ön araştırma, veri temizliği, analiz, hazırlık işlemlerinde Doğrusal veya DAG yapısında kompleks veri işleme ve dönüştürme akışlarında

Pig ismi nereden geliyor

Pig’in geliştiricilerinden Alan Gates bu konuda kendilerine çok soru geldiğini, Pig isminin bir kısaltma olmadığını ekipteki bir kişinin bu ismi bulduğunu ve sonra hoşlarına gittiğini ifade ederken, IBM’in bu konudaki yorumu bana çok daha anlamlı ve güzel geldi. “Nasılki bir domuz, önüne koyduğunuz (hatta koymadığınız) her şeyi yiyebildiği gibi, Pig’de gösterdiğiniz her türlü veriyi işleyebildiği için Pig(Domuzcuk) adını almıştır.”

Pig deyince

Aslında Pig deyince iki şeyden bahsediyoruz; birincisi Pig Latin diye isimlendirilen programlama dili, diğeri Hadoop sistemi üzerindeki Pig Latin kodlarının çalıştırıldığı ortam.

Pig latin programlama diline baktığımızda alt alta birbirini takip eden adımlar halinde prosedurel bir dil ile karşılaşıyoruz. Her adımda oluşan veri bir sonraki adıma aktarılabiliyor ancak saklanmıyor. Yani session bittiğinde ara bir adımdaki verinizi kalıcı hale getirmediyseniz ulaşamıyorsunuz. Bunu data işleme üzerine geliştirilmiş Base SAS programlama diline benzetebiliriz. SAS kodlarıda alt alta adımlardan oluşur her adımda bir işlem yapılarak devam edilir, eğer kalıcı hale getirmezseniz session bittiğinde ara adımlardaki veriler kaybolur.

Pig’i en genel haliyle 3 adımdan ibarettir diyebiliriz.

  1. Veriye ulaşma; HDFS sisteminden işlenecek veriyi load etme adımı
  2. Veri işleme veri dönüştürme amaçlı transform adımları
  3. Dump yani çıkan sonuç verisini bir yere saklama veya ekrana getirme adımı

Çalıştırma

Pig kodlarını çalıştırmak için 3 farklı opsiyonumuz var.

Script: Piglatin komutlarından oluşan .pig Script’leri oluşturmak ve bunları bir arayuz veya komut satırından çalıştırmak
Not: Normal şartlarda Pig verilen akıştaki her işlemi dönen sonuç değerine bakmaksızın baştan sona çalıştırır. Eğer akışta bir adımda hata alınırsa ve genel akışın durmasını isterseniz pig scriptinizi çalıştırırken “-F” veya “-stop_on_failure” opsiyonu verebilirsiniz. Yani;

$ pig -F pigisleri.pig
yada
$ pig -stop_on_failure pigisleri.pig
İle Pig scriptiniçalıştırmanız gerekir.
Shell mode: Grunt, Pig’in interaktif shell ortamıdır. Piglatin komutlarını shell ortamında çalıştırabilirsiniz.
Embedded: Pig programları Java kodlarının içindende çalıştırılabilir.

Pig Extensible

Pig’in güçlü yanlarından biriside Pig tarafından sağlanan fonksiyon ve komutlar sizin için yeterli olmazsa, java bilginizde yeterliyse kendi fonksiyonlarınızıda tanımlayabilir ve bunlarıda scripleriniz içinde kullanabilirsiniz.

Pig Latin’in üstün yanları

Pig’in en önemli bileşeni Hadoop üzerinde çalışan Pig Latin programlama dili veri işlemede pek çok avantaj sağlar

Prosedurel Yapısı

A = Load Data
C = Transform A
D= Transform C
Dump D

Yukarıda verilen Pig Latin’in genelleştirilmiş yapısına baktığımızda alt alta adımlarla baştan sona veri işleme akışı net olarak görülebiliyor. Her adımın sonucu bir sonraki adımda kullanılarak zincirleme anlaşılabilir bir akış sözkonusu.

Kontrol Noktaları

Pig Latin koduna baktığınızda her adımda oluşan verinin bir sonraki adıma aktarıldığını ancak saklanmadığını görüyoruz. Veri ile uğraşanlar iyi bilir, peki akışta bir yerde bir kesinti veya hata alınırsa ne olacak, çok uzun süre çalışmış veya kritik bir verinizi kaybetmeyi göze alabilir misiniz? Bunun çözümü için Pig Latin kodunuzda, akışınızın kritik noktalarına verilerinizi kalıcı tutmayı sağlayan bazı adımlar koyabilirsiniz. Yukarıdaki örnekte diyelimki C verisi kritik.

A = Load Data
C = Transform A
Store C into ‘Csakla’;
D= Transform C
Dump D

Bu şekilde C verisi Csakla ile kalıcı olarak korunur.

Optimizasyon

Pig Latin ile geliştirilmiş script kodları SQL benzeri ( Sort, Group By, Join ..) pek çok işlem yapmakta olabilirler. Bu nedenle bunları yazarken domain bilgisi, veriyi iyi tanıma, büyük veri işlemeyi bilmek gerekir.

Ayrıca Pig’in yazılan kodu nasıl yorumlayacağını nerelerde bazı hintler kullanılabileceği bilinmelidir. Optimizasyon konusu ayrı bir yazı konusudur.

DAG (Directed acyclic graph) Graf yapısı

Pig Latin kodları için veri akışı yazmaya olanak sağlar demiştik. Bu akış baştan sona birbirini takip eden adımlar olabileceği gibi bastan itibaren paralel bir şekilde ikili üçlüde devam edebilen Graf şeklinde flowlarda yapılabilir.

Pig Uzmanlığı

2008 yılında ilk versiyonu yayınlanan Apache Pig 2009 yılından hızla populer hale gelmeye basladı. Öyleki 2009 yılı sonunda Yahoo’nun aradığı hadoop job ilanlarından yarısı Pig job’larıydı.

Sonuç

Pig Latin geleneksel programlama dillerinden veya SQL’den farklı bir paralel veri işleme akışı dilidir. Veri kaynaklarının ve tiplerinin giderek çeşitlendiği, hızlı veri işlemenin daha önemli hale geldiği bir dünya Pig ‘i daha da önemli hale getirmektedir.

Pig’in ne olup ne olmadığı ile ilgili SQL ile karşılaştırmalı bir analiz yapabiliriz. SQL neredeyse günümüzde bir analiz yapmak veya bir rapor almak isteyen herkesin bildiği, tanıdığı bir sorgu dilidir. Ancak SQL bu kadar yaygın olmasına rağmen sadece RDBMS üzerinde şeması, yapısı belli veriler üzerinde sorgu için kullanılır.

Buna karşın Pig, Hadoop’un güçlü paralel ve dağıtık veri işleme yeteneğini kullanarak ham, doğal halde, farklı tiplerde pek çok veri üzerinde işlem yapmayı sağlamaktadır.

Alan Gates’in bu konuda yine güzel bir benzetme yapıyor;

“Diyelimki ben çok iyi ingilizce ve çok az da fransızca biliyorum, buna karşın eşim çok iyi fransızca konuşabiliyor. İkimizde gezmek için Fransa’ya gidiyoruz, ben Fransa gezim sırasında herkesin az çok bildiği global bir dil olan ingilizcemin geçerli olduğu daha çok turistik alanları, şehir merkezlerini rahatça gezebiliyorken, eşim ise gezisi sırasında çok iyi Fransızca biliyor olması sebebiyle, Fransa’nın pek turistlerin uğramadığı en ücra kasabalarını keşfedebiliyor, oralardaki kişilerle konuşabiliyor, benim ulaşamadığım pek çok şeyi öğrenebiliyor. Onun Fransa gezisi sonucu elde ettiği bilgiler, deneyim benden çok farklı, çünkü o yörenin ana dilini biliyor.

İşte SQL veriye ulaşma, veriyi sorgulama dünyasının ingilizcesi, herkes biliyor, herkes kullanabiliyor, ancak ulaşabildiği veriler sınırlı, Pig Latin ise lokal dilleri ifade ediyor, SQL ile ulaşılamaya yerlere, verilere ulaşıyor, daha fazla sayıda veriyi işleyebiliyor, Hadoop ile entegre olarakda paralel ve hızlı olarak bunu yapabiliyor “

Referanslar

[1] http://pig.apache.org/
[2] http://pig.apache.org/docs/r0.7.0/piglatin_ref1.html
[3] http://pig.apache.org/docs/r0.9.1/perf.html
[4] http://sites.computer.org/debull/A13mar/gates.pdf
[5] http://www-01.ibm.com/software/data/infosphere/hadoop/pig/
[6] http://developer.yahoo.com/blogs/hadoop/comparing-pig-latin-sql-constructing-data-processing-pipelines-444.html [7] http://www.slideshare.net/Hadoop_Summit/innovations-in-apache-hadoop-mapreduce-pig-hive-for-improving-query- performance
[8] http://infolab.stanford.edu/~usriv/papers/pig-latin.pdf
[9] Alan Gates, Programming Pig , O’Reilly, 2011
[10] http://hortonworks.com/blog/pig-performance-and-optimization-analysis/
[11] http://blog.cloudera.com/wp-content/uploads/2010/01/IntroToPig.pdf

Malaysia Airlines Flight 370

Pekin’e varmak üzere 8 Mart 2014 de Kuala Lumpur’dan havalanan 153 ü Çin vatandaşı olmak üzere 15 ülkeden 227 yolcu ve 12 mürettebat olmak üzere toplam 239 kişi taşıyan Boeing 777-200 tipi yolcu uçağı oniki gündür kayıp. Uçağın ve yolcuların akıbeti konusunda somut bir açıklama henüz yok. Olayın ilk günlerinde, bilinmeyen bir nedenle düştüğü düşünülen ve normal rotasında güney çin denizinde yapılan kurtarma ve arama çalışmaları son birkaç gündür uçağın rotasının ortadan kaybolmadan hemen önce değiştirildiği iddiası ile farklı bir boyut kazandı. Artık birçok değişik senaryonun düşünüldüğü ve konuşulduğu bir olay haline geldi.

Bugün itibari ile 26 ülkenin araştırma ve arama eforuna katıldığı, dünya tarihindeki en karmaşık arama operasyonlarından birini, pazarlama ve satış ağırlıklı söylemlerden uzakta kalarak, büyük veri teknolojilerinin gelmiş olduğu noktadan değerlendirmesini yapmaya çalışacağız.

Veri Kaynakları

İlişkisel Veritabanları; Öncelikle normal bir ticari uçuşta toplanan bilgilerle başlamakta fayda var. Bu bilgiler, temel olarak, uçuş mürettebatı, yolcu listeleri, uçuş seyir, uçak bakım, havayolu şirketi, uçulan lokasyonlar, bu lokasyonlardaki güvenlik ve yer hizmeti veren personel, uçağın taşıdığı eşya ve diğer yükler, yeme ve içme desteğinin alındığı firma ve kişiler, uçuşun gerçekleştiği hava koşulları vb. ilişkisel veri tabanlarında tutulan fakat genel olarak bir merkezden işlenmesi için yapılandırılmamış bilgilerdir. Bu bilgiler her uçan uçak için vardır ve 11 Eylül olaylarında teknik sebepler ve hava korsanlığı dışında sebeplerle de yakından takip edilmesi gerektiği ortaya çıkmıştır.

Kapsamı Belirli Büyük Veri; Ayrıca, bir uçağın uçması sırasında bu bilgiler dışında uçuşu gözleme amacı olmadan toplanan bilgiler de vardır ve normal bir uçuş söz konusu olduğunda bu bilgilerin kullanılması doğrudan aklımıza gelmez. Uydulardan alınan video ve fotoğraflar, değişik elektronik sinyal verileri, uçuş rotasında bulunan ve değişik amaçlarla kullanılan radar ve gözlem verileri, askeri ve sivil amaçlı uçan uçakların üzerindeki radarların topladığı veriler, uçaktaki kişilerin cep telefonlarının herhangi bir baz istasyonu ile yaptığı sinyalleşme bilgileri, yine uçaktaki yolcuların internette yaptıkları aktiviteler gibi.

Kapsamı Belirsiz Büyük Veri; Bunların dışında uçak ve gerçekleşen uçuş dışında, uçuş öncesi ve olay sırasında olaya ışık tutacak doğrudan bağlantısı olmayan ya da olduğu başta düşünülmeyen kişilerin yaptıkları telefon konuşmaları, mesajlaşmalar, internette yaptıkları her türlü faaliyet, istihbarat bilgileri var.

Bütün bu bilgilerin olayla ilgili olarak “ne? ne zaman? nerede? nasıl? neden? kim?” sorularına cevap vermek için kullanıldıkları bir dünyada, büyük veri teknolojilerinin yeri neresi dediğimizde bazı reklam ve pazarlama faaliyetlerinin yapıldığını görüyoruz. Gerçek ise 12 gündür kayıp olan söz konusu uçağın nerede olduğu ve başına ne geldiği ile ilgili herhangi bir haber veya bilginin olmadığı.

Temel Soru

Olayın genel resmini ortaya koyduk, büyük veri teknolojileri bu problemi çözmede kullanılmadı mı? Kullanıldı ise neden halen çözülemedi? Burada büyük veri teknolojilerinin bu problemin çözümünde kullanmanın zorlukları ve ileride çözüm üretebilmesi için yapılması gerekenler neler?

Çözüm Bileşenleri

Entegrasyon

Öncelikle büyük veri teknolojileri mevcut veri tabanı teknolojileri ile entegre bir şekilde çalışabilmektedir. Bu konuda önemli yol alınmış durumda ve sıkıntı olabilecek konu veri kaynaklarına doğrudan erişim haklarının olmaması olabilir. Böyle bir olayda farklı kurum ve ülkelerdeki veri tabanlarına hızlı erişim ihtiyacı olduğundan, bilgilerin paylaşımı için bir yöntem ve kuralların olup olmadığı sorusu akla geliyor. Burada farklı dillerde olan verilere erişmenin ve bu bilgileri kaynaştırmanın zorluklarının da teknik olarak çözülmesi gerektiğini belirtmek gerekiyor. Örnek olarak; Malay dili ve Çin dili uçağın kalkış ve iniş noktalarında kullanılan diller ve bu dillerdeki bilgi kaynaklarının birleştirilmesi gerekiyor.

Büyük Veri kaynaklarına Erişim ve İşleme

Büyük veri daha da zor olarak erişilebilen bilgiler olacak kuşkusuz. Uydulardan alınan olay yeri ile ilgili görüntülerin işlenmesi başlı başına bir büyük veri problemi. Şu anda Amerika Birleşik Devletleri toplam yüz ölçümüne denk olan Günay Asya da bir bölgeye ait uydu görüntülerinin işlenmesinden bahsediliyor[1]. Zaman dilimi de olayın üzerinden geçen zaman arttıkça artıyor tabii ki. Bu bilgilerin kim ile, hangi şartlarda paylaşılacağı, ve çıkan sonuçların kim tarafından kullanılacağı da net değil. Fotoğraf, radar, GSM baz istasyonu bilgileri gibi daha sayısız veri kaynağı benzer durumda. Uçaktaki kişilerin yapmış olduğu internetteki aktivitelerin bilgiye dönüştürülmesi de ayrı bir problem.

Bunların dışında daha çok istihbarat servislerinin ilgi alanına giren konularda, uluslararası güvenlik açısından konunun değerlendirilmesi gerekiyor ki bu yazının dışında tuttuğumuz bir konu.

Ele alınan problem bağlamında düşünüldüğünde, eski yöntemler yeni bir veri işleme teknolojisi ile birlikte günümüz dünyasının çok karmaşık ve hızlı çözüm gerektiren problemlerine çözüm üretmek için kullanılmak istendiğinde “acaba uydu görüntülerinde uçağın enkazlarını bulabilir miyiz?” şeklinde bazı belirli soruların cevaplanmasında kullanılabilir. Ama ilgili bütün veri kaynaklarına erişen, bunları ele alınan problem kapsamında hızla değerlendiren bir sistemin çok uzağındayız.

Farklı bir dünya kooperatif akıllar

Bunun yerine, interneti ortak insanlık aklının somutlaşması olarak gören görüşü haklı çıkaracak tarzda yaklaşımları görüyoruz. Hadoop tarzı paralel işleme ve sonuç çıkarma kapasitesine sahip bir ortam olarak web i, işlemciler olarak da bilgisayarlar dışında insanları da kullanan bir yaklaşımda uydu görüntülerini gönüllüler tek tek inceliyor ve bulgularını paylaşıyorlar [2]. İsmi Tomnod ve anlamının Moğolca da Büyük Göz anlamına geldiği söyleniyor [3]. Sloganları şu “Join the Tomnod team! Your task is to explore the satellite images and tag any important locations you find.”

Tomnod, bütün örüntü işleme algoritmalarının performansına erişmeye çalıştığı, en iyi örüntü işleme makinası olan insan beyninin, en azından benzeri bir algoritma yapılana kadar böyle bir problemde kooperatif olarak nasıl kullanılabileceğine ilişkin değişik problem çözüm yöntemlerine farklı bir örnek sunuyor.

Yeni bir çağ, yeni bilgi işleme teknikleri, fakat aklımızda çözülmesi daha önce düşünülemeyen sorular. Bu soruların çözülebilmesi, belirli yöntemlere odaklanarak değil problemlere odaklanarak yapılabilir ancak. Ülkemizde ve dünyada var olan problemlere çözüm üretmek istiyorsak, yol ve yöntemleri ararken teknolojiden faydalanma ve gerektiğinde yeni teknolojileri üretmek kaçınılmazdır. Bunun için sadece problemlere odaklanmamız gerekiyor.

Kaynaklar;

[1] http://www.theguardian.com/world/2014/mar/13/malaysia-airlines-flight-satellite-images

[2] http://www.dailymail.co.uk/news/article-2583807/Did-Malaysian-fisherman-missing-flight-MH370-flying-low-Gulf-Thailand.html

[3] http://emergencyjournalism.net/featured-tool-tomnod/

[4] http://www.tomnod.com/nod/

Büyük Veri, Veri Bilimi ve Ontoloji

Bu yazıda büyük veri ve işlenmesi için temel unsur haline gelen veri bilimcinin temel uğraş alanına ilişkin kendi fikirlerimi paylaşacağım. Okuyucu büyük verinin geçmişi, bugünü ve geleceğine ilişkin genel bir bilgi edinecek, konunun temel bileşenleri ve aralarındaki ilişkileri verilen referanslarla birlikte zenginleştirme ve kendi yorumunu oluşturma fırsatı bulacaktır. Konu hakkında bilgi ve tecrübesi olan kişiler için de farklı bir görüş alma fırsatı sunulmaktadır.

 

Büyük Veri Kavramı

1960 lı yıllardan itibaren gelişme evresinde olan veri analizi ve entegrasyonu çalışmalarının bir bütün olarak değerlendirilmesi ile Veri Bilimcisi (ing. Data Scientist) [1] teriminin 1996 yılında ortaya çıkmasını ilişkilendirebiliriz  [2, 7]. O yıllar, büyük miktarda verinin toplandığı ilişkisel veri tabanlarında önceden fark edilemeyen bilginin keşfedilmeyi beklediği yıllar olarak da hatırlanır [3] .

 

Büyük verinin anlamlandırılması ve bilgiye dönüştürülme süreci, önceki bilimsel ve teknolojik birikimlerin üzerine yeni yapılan çalışmaların ve ortaya konan yeni problemlerin eklenmesi, Hadoop [6] gibi  dağıtık işleme yapan ve kolayca erişilebilen açık kaynak kodlu bir yazılımın ortaya konması ile farklı bir aşamaya geldi. Daha önce başa çıkılabilenden çok daha fazla veri ile başa çıkmak, dolayısı ile iş dünyasına, araştırmalara yön verecek kararlar alacak bilgiler elde etmek mümkün hale geldi.

 

Büyük verinin grid hesaplama (ing. Grid Computing) yöntemleri ile işlenmesinin en az yirmi yıllık bir geçmişi olmasına rağmen, uygulandığı problem ve uygulayan kurum ve şirketlerin sayısı yıllar içinde sınırlı kaldı. Bu sınırlamada verinin her işlem öncesi ağ (ing. Network) üzerinde ilgili makineye taşınmasının problemler çıkarması ve çözümün bir türlü istenen şekilde gelmemesinin etkili olduğu söylenebilir. Yeni fikir, verinin merkezi silolarda tutulup onu işleyecek griddeki makinelere taşınması yerine, doğrudan en başta verinin gridi oluşturan makinelere dağıtılması, çalışacak prosedürün verinin olduğu makineye yollanması şeklinde ortaya çıktı. Bunu ilk çözen Google şirketi oldu ve problemi nasıl çözdüğünü 2003 yılından itibaren yayınladığı üç makale ile dünyaya duyurdu [16, 17, 18]. Böyle bir sistemin temel bileşenlerini anlatan bu makaleler, özel bir dağıtık dosyalama sistemi ( ing. Google File System -GFS), Dağıtık tablo yapısı (ing.  BigTable ) ve bu dağıtık yapıda işleme yapacak bir algoritma (ing. MapReduce) dan oluşmaktaydı.

Daha sonraki süreçte bu makalelere dayanarak yapılan çalışmalar sonucu Hadoop doğdu. Tabii bu süreçte verinin birçok makineye dağıtılarak dağıtık işlenmesinin mümkün hala getirilmesi, aynı verinin anlamlandırılması ve sonuç çıkarımında da çok yol alındığı anlamı çıkarılmamalı [8]. Bu problemin henüz tam anlamı ile çözülememesinin sebeplerini aşağıda detaylandıracağız, fakat öncelikle bu sürecin sahibi olarak isimlendirilen Veri Bilimci ve neden bu ismin ön plana çıktığı üzerinde durmakta fayda var.

 

Veri Bilimci ve Ontoloji Kavramı

Science yani bilim nedir? Latince scientia kelimesi yani bilgiden geldiği söylenir. Evren hakkında test edilebilir açıklamalara ve tahminlere dayandırılmış bilgiyi, organize eden, sınıflandıran disiplin olarak tanımlamak mümkündür [5]. Tabii bu işle meşgul olan kişiye de bilimci diyoruz. Bilimsel çalışmalar gözleme dayanır ve bu veri (ing. Data) toplamak ile eşdeğerdir. Toplanan verilerin daha önce çözülmemiş bir problemi çözmek için belli bir sistematiğe dayanarak incelenmesi bilimsel, daha önce çözülmüş bir problemin farklı bir alanda yada ölçekte uygulanması ise genellikle mühendislik olarak görülebilir.  Bu açıdan bakıldığında bilim insanı çözülmüş problemlerle uğraşmaz, yani gözlem zaten bilinen bir gerçeği, örüntüyü ortaya çıkarmak için yapılıyorsa mühendislik alanına geçilmiş olur. Verinin mühendisliği ile bilimi arasında ki bu fark nereden kaynaklanıyor? Bu konuda birçok yazı var ve henüz üzerinde uzlaşılan genel net bir tanım olduğunu söylemek güç [19, 20].

 

Konu üzerinde kendi görüşümüzü geliştirmek için, Türkiye’de yazılım dünyasında akademik çalışma yapanlar dışında pek ilgi görmediğini düşündüğümüz farklı bir disiplinden bahsetmek zorunluluğu hissediyoruz. Felsefenin bir kolu olan ve metafizik olarak adlandırılan bir çalışma alanının içinde yer alan Ontoloji [9] nin “Varlık nedir? Varoluş nedir? Bir nesnenin özellikleri veya ilişkileri nedir? Var oluş bir özellik midir? Bir nesne nasıl değişir, nasıl yok olur?” gibi sorulara cevap ararken kullandığı bilimsel birikimden yararlanmak gerekiyor. Peki büyük veriyi incelerken yazılım dünyası ontolojiden nasıl faydalanabiliyor?

 

Büyük veri içindeki bilgiye dönüştürme sürecinin en önemli aşamalarından olan nesneleri tespit etmek ve bu nesneler ve aralarındaki ilişkilerin gösterim yapısına karar verme sürecinde, bilgi mühendisi (ing. Knowledge Engineer) [13],  ontoloji biliminin de katkısı ile geliştirilmiş dilleri kullanır. Bilgi Tabanlı Sistemler (Knowledge-Based Systems) kurmak için bu kaçınılmazdır [14]. Bilimsel bir problem çözme yöntemi uygulanmadığı durumda, ontolojik [12] açıdan incelenme süreci yerine her zaman tekrar tekrar aynı analiz ve çözümleme çabalarına girişmek, ciddi zaman ve emek kaybı anlamına gelmektedir. Daha da önemlisi çözülen problem her defasında yeniden çözülmek durumundadır. Bu çalışmalar sırasında alana bağlı olarak değişik bilim dallarından insanlar işbirliği içinde olabilirler. Örneğin, fiziksel nesneler ile ilgili bir veriden bahsediyorsak, fizik bilimcisi, okyanus ile ilgili bir veriden bahsediyorsak okyanus bilimcisi, uzay ile ilgili bir veriden bahsediyorsak uzay bilimcisi gibi. Peki, ya eldeki verinin gerçek dünyada doğrudan bir karşılığı yoksa ve sanal dünya dışında var olmayan bir bilgiden söz ediyorsak hangi bilim dalından yardım alınacak? İşte bu noktada veri bilimcisinin devreye girmesi gerekiyor ve veri dünyasında olan nesneler ve ilişkileri konusunda bilgi mühendisi ile birlikte çalışıyor. Tabii, bilgi mühendisi zaten bilgi teknolojileri dünyasından olan bir kişi olduğundan dolayı veri bilimcisi ile bilgi mühendisini çoğu durumda aynı kişide birleştirmek pratik bir sonuç olacaktır. Ontolojik olarak incelenen veri, özellikle alan bilgisinin de olduğu bir ontolojik yapı içerisinde incelendiğinde, tekrarlar algoritmalara aktarılmış olacak, veri bilimcisi daha önce yapılmayana odaklanacaktır [10]. Bu seneki Ontology Summit 2014 ün ana konusu ve vurgusu bu odaklanmayı somut bir şekilde göstermektedir “Big Data and Semantic Web Meet Applied Ontology” [11].

 

Büyük Veri İle İlgili Yeni Yaklaşımlar

1989 da HTTP (HyperText Transfer Protocol) protokolünü ve HTML (HyperText Markup Language) formatını icad ederek; yazı, resim ve video içeren zengin içerikli dokümanların birbirine bağlanması fikri olan WWW (World Wide Web) nin mucidi ve babası olan Tim Berners-Lee, benzer  bir devrimin verilerin birbirine bağlanması ile de gerçekleşeceğine inanıyor [15]. Lee nin Bağlı Veriler (ing. Linked Data) olarak adlandırdığı verilerin birbirine bağlanması ile Semantic Web gerçek olacak ve Web de yer alan verilerin otomatik olarak algoritmalarla işlenebilir bir semantik yapıda olması sağlanabilecek. Her yeni gelen verinin daha ilk saklanma aşamasında aynı insan beyninde olduğu gibi ilişkili olduğu bilgi ile birlikte saklanması bu şekilde çok büyük miktarda bir sonradan işleme (ing. post processing) gereksinim duyulmadan aranan bilginin bulunması ve çıkarım yapılabilmesinin mümkün olması sağlanmış olacak. Yani büyük veride en acılı süreç olan verilerin toplanması ve tasnif edilmesi aşaması Web in kendisinin bu şekilde organize olması ile önceden çözülmüş olacak.

 

Veri Bilimcisinin Kullandığı Yaklaşımlar

Verinin yapılanması dışında, işlenip bilgiye dönüştürülürken kullanılacak algoritmalar veri bilimcisinin sıklıkla başvurduğu araçlar olmak durumundadır. Bu algoritmalardan en çok kullanılanlar veriyi ele alma tarzına göre iki yaklaşıma dayanmaktadır.

 

Birinci yaklaşım olarak, gözlenen sistemden elde edilen verinin stokastik yani bir şekilde rastgelelik taşıdığı ve çözüm için verinin modellenmesinin öncelikle bu rastgeleliği modellemekten geçtiği düşüncesi hakimdir ve istatistiki algoritmalara dayanır.

 

İkinci yaklaşım ise aynı verinin yapısının bilinmez kabul edildiği ve bir veri modeli kurmadan doğrudan uygun algoritma ile sonuç elde etmenin mümkün olduğu düşüncesini savunur ve bilgisayar bilimlerinin bir alt dalı olan makine öğrenmesi içinde ele alınır [4]. Yapay sinir ağları ve karar ağaçları bu yöntemlere örnek olarak verilebilir. İki yaklaşımın da başarılı olduğu alanlar vardır ve bu alanlar iki yaklaşımın da halen kullanılmasının ana nedenidir. İlk yaklaşım ile ilgili adı geçen çalışmada 205.sayfada “.. how the commitment to data modeling has prevented statisticians from entering new scientific and commercial fields where the data being gathered is not suitable for analysis by data models.” denerek istatistikçilerin sadece modellemeye uygun veriler üzerinde yoğunlaşarak yapısal olmayan verilerin bir anlamda ihmal edildiğine dikkat çekilmektedir.

 

Son olarak, bilgiye ulaşmak dışında bunun kullanılabilirliği de günümüzün en önemli konularından biridir. Ayrı bir uzmanlık alanı olarak da görenler vardır. Özellikle bellekte analitik çözümleme (ing. in-memory analytics ) ve bunun görsel bir şekilde karar vericilere sunulması büyük veri ile birlikte üretilen çözümün bir parçası haline gelmiştir. Büyük analitik çözüm firmaları geçtiğimiz yıl ve bu yıl yaptıkları çalışmalarda tamamen bu konuya odaklanmış görünmekteler.

 

Özetle;

Veri bilimci, bilimsel yöntemler kullanarak büyük veriyi

  • analiz ederek gösterimi için en uygun yapıya karar verir ve tasniflemesini yapar,
  • dağıtık bir şekilde otomatik olarak işleyecek mimari konusunda uzmanlığını ortaya koyar,
  • kullanımına ilişkin temel kural ve çıkarım mekanizmasını ortaya koyar,
  • faydalanma yöntemlerini de ortaya çıkarır ve sunar.

 

 

Kaynaklar;

[1] http://devveri.com/big-data/data-scientist-veri-bilimci-kimdir

[2] http://www.forbes.com/sites/gilpress/2013/05/28/a-very-short-history-of-data-science

[3] From Data Mining to Knowledge Discovery in Databases, Usama Fayyad, Gregory Piatetsky-Shapiro, and Padhraic Smyth, AI Magazine Volume 17 Number 3 1996

[4] 2001 Leo Breiman, “Statistical Modeling: The Two Cultures”, Statistical Science, , Vol. 16, No. 3, 199–231, 2001

[5] http://en.wikipedia.org/wiki/Science

[6] http://hadoop.apache.org/

[7] What is Data Science ? Fundamental Concepts and a Heuristic Example, Proceedings of the Fifth Conference of the International Federation of Classification Societies (IFCS-96), Kobe, Japan, March 27–30, 1996

[8] http://breakinggov.com/2012/04/23/big-data-systems-need-data-science-and-knowledge-bases/

[9] http://www.cangungen.com/2011/03/10/ontoloji-varlik-felsefesi/

[10] http://vitalflux.com/key-to-big-data-data-science-data-framework/

[11] http://ontolog.cim3.net/OntologySummit/2014

[12] Yazılım Mühendisliğinde Ontolojilerin Kullanımı, Görkem Giray, Murat Osman Ünalır

[13] http://en.wikipedia.org/wiki/Knowledge_engineering

[14] International Conference on Knowledge Engineering and Ontology Development, 21-24 October 2014

[15] http://www.ted.com/talks/tim_berners_lee_on_the_next_web

[16] http://research.google.com/archive/gfs.html

[17] http://research.google.com/archive/mapreduce.html

[18] http://research.google.com/archive/bigtable.html

[19] http://www.datasciencecentral.com/profiles/blogs/data-scientists-vs-data-engineers

[20] http://www.datasciencecentral.com/profiles/blogs/data-scientist-versus-data-engineer

[21] http://www.visual-analytics.eu/faq/

 

 

Hive ile HBase Entegrasyonu

hbase_logoHadoop ekosistemindeki projelerin en büyük avantajlardan birisi de birbirleriyle uyumlu olarak çalışabilmeleri. Bu yazımızda HBase üzerindeki verileri Hive üzerinden sorgulamayı inceleyeceğiz.

HBase ile Hive’ı entegre edebilmek için ilk adım olarak gerekli kütüphanelerin classpath üzerinden erişilebilir olmasını sağlamak. Aşağıdaki jar dosyalarını (tabii ki uygun versiyon numaraları ile) Hive’ın ya da direkt olarak Hadoop’un lib dizini içerisine bulunması gerekiyor:

hive-hbase-handler-0.9.0.jar
hbase-0.92.0.jar
zookeeper-3.3.4.jar
guava-r09.jar

Örnek olması açısından HBase tarafında bir tablo yaratmak amacıyla Sqoop kullanabiliriz. Veritabanımızda bulunan mevcut bir tabloyu HBase’e Sqoop üzerinden aktarıyoruz:

sqoop import --driver com.mysql.jdbc.Driver --connect "jdbc:mysql://myhost/test" --username myuser --password mypass --table mytable --hbase-table mytable --column-family c --hbase-create-table

Sqoop parametrelerinde –hbase-create-table ile verileri HBase’e aktaracağımızı, –hbase-table ile de HBase tarafındaki tablo ismini belirtiyoruz. Komutun çalışması sona erdikten sonra HBase shell üzerinden verileri kontrol edebiliriz:

$ hbase shell
HBase Shell; enter 'help' for list of supported commands.
Type "exit" to leave the HBase Shell
Version 0.94.6-cdh4.5.0, rUnknown, Wed Nov 20 15:46:19 PST 2013

hbase(main):001:0>scan 'mytest', {LIMIT=>1}
ROW                                           COLUMN+CELL
 1                                            column=c:field1, timestamp=1392992550443, value=val1
 1                                            column=c:field2, timestamp=1392992550443, value=test1
1 row(s) in 0.1050 seconds

Daha sonrasında Hive tarafında HBase’deki tablomuzu external table olarak tanımlıyoruz:

CREATE EXTERNAL TABLE mytest(rowkey STRING, field1 STRING, field2 STRING)
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES ('hbase.columns.mapping' = ':key,c:field1,c:field2')
TBLPROPERTIES ('hbase.table.name' = 'mytest');

Tanımı yaparken HBaseStorageHandler sınıfını kullanıyoruz. Tabloyu yaratırken verdiğimiz kolon tanımları ile SerDe tanımlarının birebir örtüşmesi gerekiyor. Yani :key ile HBase tarafındaki rowkey değerini rowkey alanı ile, c:field1 alanını da field1 alanı ile örtüştürüyoruz. hbase.table.name parametresi ile de HBase tarafındaki tablo ismini belirtiyoruz.

Tanımı yaptıktan sonra artık Hive tarafında sorgulama yapabilir hale geliyoruz:

hive> SELECT * FROM mytest limit 3;
OK
1	val1	test1
2	val2	test2
3	val3	test3

Her ne kadar HBase üzerindeki verileri Hive ile sorgulamak kulağa çok hoş gelse de bu entegrasyon halen geliştirme aşamasında. Yaptığım denemelerde çok verimli sonuç aldığımı malesef söyleyemeyeceğim. Sorgular ya çok uzun sürüyor ya da bir noktada başarısız oluyor. Ancak geliştirmeler tamamlandığında oldukça kullanışlı olacağını tahmin ediyorum.

Daha detaylı bilgi için ilgili sayfayı ziyaret edebilirsiniz.

Hive JDBC Bağlantısı

hive_logo_mediumHive üzerindeki verilere erişmenin birkaç yöntemi var. Bu yöntemlerden birisi de JDBC sürücüsünü kullanmak. Hive JDBC sürücüsü ile verileri programatik olarak sorgulamak ve bir SQL arayüzü (örneğin SQuirreL) kullanmak mümkün hale geliyor.

Hive tarafından yönetilen verilerin dışarı açılmasını HiveServer2 uygulaması sağlıyor. Önceden HiveServer (ya da ThriftServer) olarak adlandırılan bu uygulama aynı anda sadece tek bir bağlantıya izin verdiği ve herhangi bir güvenlik desteği bulunmadığı için geliştirilerek HiveServer2 adını almış. JDBC sürücüsü de bu uygulama üzeriden thrift kullanarak verilere erişiyor.

JDBC Kullanarak Erişim

JDBC kullanarak erişim oldukça kolay, maven ayarları şöyle:

<dependency>
  <groupId>org.apache.hive</groupId>
  <artifactId>hive-jdbc</artifactId>
  <version>0.10.0-cdh4.5.0</version>
</dependency>

Örnek kod ise şu şekilde:

package com.devveri.hive.jdbc.test;

import org.junit.Test;
import java.sql.*;

public class HiveJdbcTest {

    private static final String JDBC_DRIVER = "org.apache.hive.jdbc.HiveDriver";
    private static final String JDBC_URL = "jdbc:hive2://myhost:10000/test";
    private static final String JDBC_USER = "";
    private static final String JDBC_PASS = "";

    @Test
    public void test() throws ClassNotFoundException, SQLException {
        Class.forName(JDBC_DRIVER);

        Connection con = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            con = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASS);
            stmt = con.createStatement();
            rs = stmt.executeQuery("select * from test.nyse limit 10");
            while (rs.next()) {
                System.out.println(String.format("%s\t%s\t%f",
                        rs.getString("exchange"),
                        rs.getString("date"),
                        rs.getDouble("stock_price_open")));
            }
        } finally {
            if (rs != null) {
                rs.close();
            }
            if (stmt != null) {
                stmt.close();
            }
            if (con != null) {
                con.close();
            }
        }
    }

}

SQuirreL Üzerinden Erişim

SQuirreL, Java ile geliştirilmiş bir SQL arayüzü. Bağlanmak istediğiniz veritabanının JDBC sürücüsünü tanıtarak arayüz üzerinden sunucuya erişmenizi sağlıyor. Hive JDBC driver kullanarak erişim yapmak için aşağıdaki jar dosyalarına ihtiyaç var:

Screen Shot 2014-02-23 at 01.52.20

 Ardınan bağlantı ayarları yapılarak erişimi test edebilirsiniz:

Screen Shot 2014-02-21 at 15.44.28