Makine Öğrenmesi ile Bitcoin Analizi

Merhaba, bilindiği üzere bitcoinin fiyatı çıkan yeni haberlere göre (Çin bitcoini yasakladı, Amerikan bankaları bitcoin alımını yasakladı … ) değişkenlik gösterebiliyor.Bugün bitcoin hakkında atılan tweetlerin sınıflandırılmasıyla bitcoinin duygu analizini python ile nasıl gerçekleştirebileceğimizden bahsedeceğim.
Öncelikle tweetleri toplayabilmek için tweepy kütüphanesinden faydalanmamız gerekiyor.Daha önceki yazılarımdan birinde tweepy ile nasıl veri çekebileceğimizden bahsetmiştim, ilgili yazıya buradan ulaşabilirsiniz.

from tweepy import Stream
from tweepy import OAuthHandler
from tweepy.streaming import StreamListener
import time
import json
import tweepy
 
consumerKey="xxxx"
consumerSecret="xxxx"
accessToken="xxxx-xxxx"
accessSecret="xxxx"
 
class listener(StreamListener):
    def on_data(self, data):
        all_data = json.loads(data)
        tweet = all_data["text"]
        try:
          print(tweet)
        except:
            pass
        time.sleep(0.3)
        return(True)
    def on_error(self, status):
        print (status)
 
def main():
    auth = OAuthHandler(consumerKey, consumerSecret)
    auth.set_access_token(accessToken, accessSecret)
    while True:
        twitterStream = Stream(auth, listener())
        twitterStream.filter(track=["bitcoin"], async = True, stall_warnings=True)
        time.sleep(6000) 
        twitterStream.disconnect()
 
if __name__ == "__main__":
    main()

Yukarıdaki kod ile bitcoin hakkında atılan tweetleri çekebiliyoruz.Şimdi gelecek tweetleri sınıflandırmamız lazım, ben 3 tür sınıfa ayırmayı uygun gördüm.Olumlu tweetler için “pozitif”, olumsuzlar için “negatif” ve duygu içermeyenler için nötr (“Bitcoin price: 11.000 USD” gibi).
Sınıflandırma için ise naive bayes algoritmasını kullandım.Algoritmayı TextBlob kütüphanesinden faydalanarak kullanabiliriz.

from textblob.classifiers import NaiveBayesClassifier
from textblob import TextBlob

Algoritmadan faydalanmak için öncelikle onu beslememiz gerekiyor.Bunun için pozitif,negatif ve nötr olan tweetler bularak ayrı ayrı dosyalara yazdım, diziye atayarak train verisi olarak ekledim.
Ayrıca sonuçların ne kadar etkili olduğunu test edebilmek için aynı şekilde test verilerini de ekledim.

def getData(filename,group,arr): 
    for i in open(filename):
            example_sent = i.rstrip('\n')
            word_tokens = word_tokenize(example_sent)
            arr.append([word_tokens , group])
def main():
    auth = OAuthHandler(consumerKey, consumerSecret)
    auth.set_access_token(accessToken, accessSecret)
    train = []
    test = []
    getData('data/pos.txt', 'pos',train)
    getData('data/neg.txt', 'neg',train)
    getData('data/neut.txt', 'neut',train)
    getData('data/test/testNeut.txt', 'neut',test)
    getData('data/test/testPos.txt', 'pos', test)
    getData('data/test/testNeg.txt', 'neg', test)
 
    global cl
    cl = NaiveBayesClassifier(train)
 
    while True: 
        print(cl.accuracy(test))
        twitterStream = Stream(auth, listener())
        twitterStream.filter(track=["bitcoin"], async = True, stall_warnings=True)
        time.sleep(6000) 
        twitterStream.disconnect()

Ardından gelen tweetleri hemen sınıflandırmaya sokarak pozitif veya negatif olmasına göre sayaca +1/-1 puan ekleyerek gelecek verilerden bir grafik elde etmeyi düşündüm. Matplotlib ile verileri görselleştirerek daha hoş bir inceleme yapılabilir.
Ayrıca sınıflandırılacak tweetlerin farklı dillerde olabiliyor olması sıkıntı oluşturuyordu.Bu yüzden sadece ingilizce atılan tweetleri kullanmaya karar verdim.TextBlob kütüphenesi içerisinde detect_language() fonksiyonunu kullanarak ingilizce tweetleri ayıkladım.

import matplotlib.pyplot as plt
class listener(StreamListener):
    x = 0
    y = 0
    def on_data(self, data):
        all_data = json.loads(data)
        tweet = all_data["text"]
        analysis = TextBlob(tweet)
        try:
            if analysis.detect_language() == 'en':
                if analysis not in check:
                    print(tweet,cl.classify(filtered_words))
                    check.append(analysis)
                    if cl.classify(tweet) == 'pos':
                        listener.y += 1
                    elif cl.classify(tweet) == 'neut':
                        pass
                    else:
                        listener.y -= 1
                    plt.ion()
                    listener.x += 1 # x ekseni
                    plt.scatter(listener.x,listener.y)
                    plt.pause(0.05)
                    else:
                        pass
        except:
            pass

Gelen tweetlerde filtrelemeler yaparak (Gereksiz kelimeleri kaldırma (he,she,do,herself …), Tweet içerisindeki url ve etiketleri kaldırma) başarı oranını artırdım.Çok sayıda bot hesap sürekli olarak belirli tweetleri retweet yaptığı için retweet olanları da işleme almadım.

class listener(StreamListener):
    x = 0
    y = 0
    def on_data(self, data):
        all_data = json.loads(data)
        tweet = all_data["text"]
        tweet = re.sub(r"http\S+", "", tweet)
        analysis = TextBlob(tweet)
        stop_words = set(stopwords)
        filtered_words = set(analysis.words.lower()) - stop_words 
        for i in set(filtered_words): 
            if i[:1] == '@':
                set(filtered_words).remove(i)
        try:
            if analysis.detect_language() == 'en': 
                if analysis[:2] == 'RT':
                    pass
                else:
                    if analysis not in check:
                        print(tweet,cl.classify(filtered_words))
                        check.append(analysis)
                        if len(check) > 10:
                            del check[:]
                        if cl.classify(tweet) == 'pos':
                            listener.y += 1
                        elif cl.classify(tweet) == 'neut':
                            pass
                        else:
                            listener.y -= 1
                        plt.ion()
                        listener.x += 1
                        plt.scatter(listener.x,listener.y)
                        plt.pause(0.05)
                    else:
                        pass
        except:
            pass
 
        time.sleep(0.3)
        return(True)
    def on_error(self, status):
        print (status)

Ve sonuçlar aşağıdaki gibi oldu. Tabi ki veriler genişletildiğinde oran değişebilir.


Kodların tamamına github üzerinden ulaşabilirsiniz.

İlk Yorumu Siz Yapın

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir