Web Sayfası olarak Machine Learning Modellerinin Kullanıma Açılması

Herkese Selam,

Machine Learning modellerinin kullanıma açılması ile ilgili opsiyonları bir süredir paylaşıyorum. Bu opsiyonlardan birini bir önceki yazımda paylaşmıştım. Link‘e tıklayarak bu yazıya gidebilirsiniz. Bu yazıda ise farklı bir kullanıma açma senaryosu ile ilgili bir örnek yapmayı planlıyorum. Umarım farkındalık anlamında faydalı bir yazı olur.

Girişi, yukarıda linkini paylaşmış olduğum bir önceki yazımdan alıntı yaparak başlamak istiyorum.

“Hepimizin bildiği üzere Makine Öğrenimi ve uygulamaları günümüzün en trend konularının başında geliyor. Bireysel kullanıcılardan kurumsal büyük organizasyonlara kadar bir çok oyuncu makine öğrenimi uygulamaları geliştirmeye çalışıyor. Bu konu ile ilgili mesai harcayan herkesin bildiği üzere bu projelerin gelişimi standart yazılım geliştirme akışından bir miktar farklı. Çözmek istediğimiz probleme ait modeli önce prototipliyoruz daha sonra belirli bir süre test edip parametrelerini en iyileyerek modelimizi nihai halini almasını sağlıyoruz. Modelimiz oldu dediği noktada da bu modeli kullanıma açma kısımına geçiyor. Tam bu noktada mevcut skill setimizin yanında bir miktar yazılım geliştirme ve veri mühendisliği bilmemiz gerekiyor çünkü standart yazılım geliştirme yöntemleri ile bundan sonraki kısımları halletmemiz gerekiyor. Yazımıza konu olan kısımda tamda bu noktada başlıyor.” 

Bu yazıya konu olacak modelimiz bir önceki yazımda kullanmış olduğum modelin bire bir aynısı dolayısıyla bu yazıdaki örneği daha iyi kavrayabilme adına bir önceki yazıdakinin aynısı. Yani daha önce bu blogta paylaşmış olduğum “Doğal Dil İşleme (NLP) ile Sentiment (Duygu) Analizi Tespiti” yazısında paylaşmış olduğum model üzerinden çalışmayı yapacağım ve yine önemle vurgulamak isterimki bu yazının yazılma amacı state of the art bir sentiment analyzer yapmak değil.

“Öncelikle senaryomdan bir miktar bahsedeyim. Bir sentiment analizi modeli geliştirmek istiyorum. Bu modeli imdb, yelp ve amazon’dan toplanmış bir veri seti ile eğitip basit bir sentiment tahmin modeli geliştireceğim. Daha sonra bu modeli bitirdikten sonra bir web sayfası tasarlayıp bu web sayfası üzerinden modeli son kullanıcıların kullanımına açacağım.

Bu yazıya konu olan modeli daha önce paylaşmış olduğum yazımdan daha detaylı anlayabilirsiniz. Ben sadece modeli elde ettiğim kod kısmını bütünlük bozulmasın diye copy paste edeceğim.

import pandas as pd
import numpy as np
import pickle
import sys
import os
import io
import re
from sys import path
import numpy as np
import pickle
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelBinarizer
import matplotlib.pyplot as plt
from string import punctuation, digits
from IPython.core.display import display, HTML
from nltk.corpus import stopwords
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
from nltk.tokenize import RegexpTokenizer
#Amazon Data
input_file = "../data/amazon_cells_labelled.txt"
amazon = pd.read_csv(input_file,delimiter='\t',header=None)
amazon.columns = ['Sentence','Class']

#Yelp Data
input_file = "../data/yelp_labelled.txt"
yelp = pd.read_csv(input_file,delimiter='\t',header=None)
yelp.columns = ['Sentence','Class']

#Imdb Data
input_file = "../data/imdb_labelled.txt"
imdb = pd.read_csv(input_file,delimiter='\t',header=None)
imdb.columns = ['Sentence','Class']


#combine all data sets
data = pd.DataFrame()
data = pd.concat([amazon, yelp, imdb])
data['index'] = data.index
#Total Count of Each Category
pd.set_option('display.width', 4000)
pd.set_option('display.max_rows', 1000)
distOfDetails = data.groupby(by='Class', as_index=False).agg({'index': pd.Series.nunique}).sort_values(by='index', ascending=False)
distOfDetails.columns =['Class', 'COUNT']
print(distOfDetails)

#Distribution of All Categories
plt.pie(distOfDetails['COUNT'],autopct='%1.0f%%',shadow=True, startangle=360)
plt.show()
#Text Preprocessing
columns = ['index','Class', 'Sentence']
df_ = pd.DataFrame(columns=columns)

#lower string
data['Sentence'] = data['Sentence'].str.lower()

#remove email adress
data['Sentence'] = data['Sentence'].replace('[a-zA-Z0-9-_.]+@[a-zA-Z0-9-_.]+', '', regex=True)

#remove IP address
data['Sentence'] = data['Sentence'].replace('((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}', '', regex=True)

#remove punctaitions and special chracters
data['Sentence'] = data['Sentence'].str.replace('[^\w\s]','')

#remove numbers
data['Sentence'] = data['Sentence'].replace('\d', '', regex=True)

#remove stop words
for index, row in data.iterrows():
    word_tokens = word_tokenize(row['Sentence'])
    filtered_sentence = [w for w in word_tokens if not w in stopwords.words('english')]
    df_ = df_.append({"index": row['index'], "Class":  row['Class'],"Sentence": " ".join(filtered_sentence[0:])}, ignore_index=True)

data = df_
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import cross_val_score
from sklearn.metrics import accuracy_score
from sklearn.neural_network import MLPClassifier
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import SGDClassifier


#grid search result
vectorizer = TfidfVectorizer(analyzer='word',ngram_range=(1,2), max_features=50000,max_df=0.5,use_idf=True, norm='l2') 
counts = vectorizer.fit_transform(X_train)
vocab = vectorizer.vocabulary_
classifier = SGDClassifier(alpha=1e-05,max_iter=50,penalty='elasticnet')
targets = y_train
classifier = classifier.fit(counts, targets)
example_counts = vectorizer.transform(X_test)
predictions = classifier.predict(example_counts)
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import classification_report

#Model Evaluation
acc = accuracy_score(y_test, predictions, normalize=True)
hit = precision_score(y_test, predictions, average=None,labels=classes)
capture = recall_score(y_test, predictions, average=None,labels=classes)

print('Model Accuracy:%.2f'%acc)
print(classification_report(y_test, predictions))

Evet modelimizi oluşturduk. Bundan sonra ihtiyacımız olan şey oluşturduğumuz modeli ve modelin vocabulary çıktısını pickle ile kayıt etmek. Daha sonra geliştireceğimiz web sayfasında bu outputları kullanacağız.

### model_save ###
pickle.dump(classifier,open("model_sentiment.pkl","wb"))
pickle.dump(vocab,open("vocab_sentiment.pkl","wb"))

Modelimiz ile ilgili çıktılarımız diske kayıt edildi. Şimdi bu modele input olarak gönderilecek text’in sentimentini bulup geriye dönecek web sayfasının geliştirmesine başlayabiliriz.

Geliştirmeyi python ile yapacağımdan dolayı python’ın flask kütüphanesini kullanacağım. Flask python ile web tabanlı uygulamalar geliştirmenizi sağlayan bir kütüphane. Bende bu kütüphaneyi kullanarak bir web servis geliştireceğim. Öncelikle geliştirme ortamımıza flask kurulumu yapalım.

pip install -U Flask

veya anaconda kullanıcıları için 

conda install -c anaconda flask

Flask kurulumumuzda tamamlandığına göre şimdi web sayfamızın geliştirmesini yapabiliriz.

Geliştirmeye başlamadan önce kendi localimde kurmuş olduğum dizin yapısını göstermek istiyorum. Böyle bir çalışma için sizinde benzer bir dizin yapısı kurmanızın işe yarayacağını düşünmekteyim. Zaten bu bir web uygulaması olacağı için ana kodu yazdığımız webform.py çalıştığı esnada render edeceği .html dosyasını /templates dizini altında arayacak. Dolayısıyla html sayfanızı geliştirdikten sonra templates dizini altına atmanız gerekecek. Aşağıda başarılı şekilde çalışacak dizin yapısını görebilirsiniz.

Dizin yapımda da göreceğiniz üzere geliştirdiğim ve outputlarını aldığım model çıktılarımı models folder’ının altına taşıdım. Templates dizini altına webform.html dosyamı yaratıp koydum. Aynı şekilde ana dizin altına da webform.py isimli kod dosyamı oluşturup kayıt ettim.

Bu uygulama web sayfası üzerinden kullanıcıya ulaştırılacağı için çok basit bir tasarım la kullanıcının text girişi yapıp sonucu göreceği basit bir html form tasarlıyorum. Bu web sayfası, web teknolojilerinin sunmuş olduğu tüm güncel alt yapılar ile donatılabilir ben sadece olabildiğince basit bir tasarım ile nasıl yapıldığını göstermek istiyorum.

“Not: Form inputunu bir tweet olarak kurguladım. Bunun hiç bir önemi yok :)”

webform.html

<form method="POST">
	<br><b>Enter Tweet here...</b></br>
	<textarea rows="4" cols="50" name="tweet">
	</textarea>
	<br></br>
    <input type="submit">
    <br></br>
    <h1><b> Result: </b> {{ value }} </h1>
</form>

Şimdi yarattığımız formun nasıl bir şey olduğuna bakalım.

Evet görüldüğü üzere tasarımımız çok basit. Şimdi bu formu kullacak ve modelimizi çalıştırıp yukarıdaki sayfadan gönderilen text’in sentimeni bulup geri form’a cevabı döndüren python kodunuz yazalım.

webform.py

Burada dikkat edilmesi gereken üç şey var. Birincisi yazdığımı html kodunun nasıl çağırıldığı. İkincisi model outputlarımızı load edip kullanıma hazır hale getirmek.
Üçüncüsü ise dışarıdan parametre olarak gelecek text’i bir değişken içerisine almak ve dördüncüsü bulunan sonucun web sayfasına geri döndürülmesi. Bu satırları vurgulamak açısından bold yapıyorum.

from flask import Flask, request, render_template, url_for
import pickle
import time
import os
from sklearn.feature_extraction.text import TfidfVectorizer
import pandas as pd
import io
import re
from sys import path
import numpy as np
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelBinarizer
import matplotlib.pyplot as plt
from string import punctuation, digits
from flask import Flask, request, render_template, url_for

start_time = time.time()

app = Flask(__name__)
app.config["DEBUG"] = True

@app.route('/')
def my_form():
    return render_template('webform.html')

@app.route('/', methods=['POST','GET'])
def home():
	vec = open("models/model_sentiment.pkl", 'rb')
	loaded_model = pickle.load(vec)

	vcb = open("models/vocab_sentiment.pkl", 'rb')
	loaded_vocab = pickle.load(vcb)

	txt = request.form['tweet']
    
	examples = txt

	examples = examples.lower()
	examples = examples.replace('\n',' ')
	examples = re.sub(r'[a-zA-Z0-9-_.]+@[a-zA-Z0-9-_.]+', ' ', examples)
	examples = re.sub(r'@[A-Za-z0-9]+', ' ', examples)
	examples = re.sub(r'((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}', ' ', examples)
	examples = re.sub(r'[^\w\s]', ' ', examples)
	examples = re.sub(r'\d', ' ', examples)
	examples = re.sub(' +',' ',examples) 
	examples = [examples]
	
        from sklearn.feature_extraction.text import TfidfTransformer
	from sklearn.feature_extraction.text import TfidfVectorizer
	count_vect = TfidfVectorizer(analyzer='word',ngram_range=(1,2), max_features=50000,max_df=0.6,use_idf=True, norm='l2',vocabulary=loaded_vocab)
	x_count = count_vect.fit_transform(examples)
	predicted = loaded_model.predict(x_count)
	result=''
	if predicted[0] == 0:
	    result= 'Negative'
	elif predicted[0] == 1:
	    result= 'Positive'
	return render_template('webform.html',value=result)

Evet geliştirmeleri tamamladık. Şimdi yazdığımız webform.py kodunu çalıştıralım.

env FLASK_APP=webform.py flask run


Evet servisimiz ayağa kalktı ve endpoint adresi ekranda bize gösterildi. Şimdi servisi test edelim. Test için ekranda görünen endpointi browsera yazmamız yeterli olacak ve istediğimiz bir input ile testimizi yapacağız.

Evet görüldüğü üzere web sayfamızı yazdığımız python kodu üzerinden ayağa kaldırdık ve machine learning modelini son kullanıcının rahatlıkla kullanabileceği bir hale getirmiş olduk.

About ... from Emrah METE

Bilgisayar Mühendisi
This entry was posted in Root, Uncategorized and tagged , , , , , , , , , , . Bookmark the permalink.

2 Responses to Web Sayfası olarak Machine Learning Modellerinin Kullanıma Açılması

  1. Pingback: Machine Learning Uygulamalarının Docker Üzerinden Servis Edilmesi | Emrah METE

  2. Ne güzel bir blog sayfası!

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.