22 Şubat 2020 Cumartesi

SQL Server 2019 üzerinde Makine Öğrenimi - 4 (Machine Learning Services in Database (R and Python)) (Eğitilmiş Model ile Tahminleme)

Serinin bu yazını kadar SQL Server özelliklerinden bir olan Machine Learning Services in Database özelliğini kullanabilmek için gerekli ortamı hazırladık. R ve Python gibi dillerdeki scriptlerin nasıl çalıştırıldığından bahsettik. Bir Machine Learning modeli eğittik ve SQL Server tablosunda depoladık. Bu yazıdaki işleyeceğimiz senaryoyu uygulayabilmek için önceki yazılara göz atmanızı öneririm.

Önceki yazılara şu linklerden erişebilirsiniz:

SQL Server 2019 üzerinde Makine Öğrenimi - 1 (Machine Learning Services in Database (R and Python))

SQL Server 2019 üzerinde Makine Öğrenimi - 2 (Machine Learning Services in Database (R and Python)) (Tablo ve DataFrame ile Çalışmak)

SQL Server 2019 üzerinde Makine Öğrenimi - 3 (Machine Learning Services in Database (R and Python)) (ML modeli eğitmek ve depolamak)

Bu yazımızda daha önce eğittiğimiz ve SQL Server tablosunda varbinary olarak depoladığımız modeli Python scriptinde okuyup model nesnesi haline getireceğiz. Daha sonra bu nesne yardımıyla tahminleme yapacağız.

Senaryomuz tam olarak şöyle:
  1. Daha önce varbinary olarak depoladığımız eğitilmiş modelimizi seçeceğiz.
  2. Seçtiğimiz modeli kullanarak tahminleme yaptığımız Python scriptini bir procedure ile kapsülleyeceğiz.
  3. Tahminlemek istediğimiz verileri yeni proceduree parametre olarak verip tahmin sonuçlarını görüntüleyeceğiz.
Bu yazıda SSMS ve Azure Data Studio aracını kullanabilirsiniz. Ben önceki yazılarda olduğu gibi Azure Data Studio aracını kullanmaya devam edeceğim.

Senaryomuzu adım adım işleyelim.

1- Depoladığımız modeli seçelim:


Daha önce MPGCarsDB isimli veritabanındaki mpgcars tablosunda bulunan verilerle model eğitmiş ve bu modeli mpgcars_model isimli tabloya yüklemiştik. Bu tablodan filtreleyerek seçtiğimiz modeli tahminleme yaptığımız Python kodlarına göndereceğiz.

Depoladığımız modele bakalım:

USE MPGCarsDB
GO

select * from mpgcars_model



2- Tahminleme yapacak procedureü kapsülleyen procedure yazalım:


Python scriptlerini sp_execute_external_script procedureünün @script parametresi ile çalıştırıyorduk. Bu procedureün @input_data_1 parametresine tahmin için kullanacağımız satırları veren SELECT sorgusunu yazıyoruz. Bu satırları procedure içerisinde @input_data_1_name parametresiyle belirttiğimiz mpgcars adıyla kullanabileceğiz. Tahminlemek için bir eğitilmiş modele ihtiyacımız var. Bu eğitilmiş modeli, tanımını @params parametresinde yaptığımız @modelbin isimli parametreye verip script içerisinde kullanacağız. Sonrasında tahminlemede kullanılacak satırları ve tahminleri WITH RESULT SETS ile belirttiğimiz formatta bir tablo olarak görebileceğiz. 

sp_execute_external_script procedureünü kolaylık olsun diye usp_PredictUsingModelBin isimli procedure ile kapsülleyelim ve eğitilmiş model ile SELECT sorgusunu parametrede gönderelim.

CREATE OR ALTER PROC usp_PredictUsingModelBin (@Tmodelbin varbinary(max),@rows nvarchar(500))
AS
BEGIN
EXEC sp_execute_external_script
        @language = N'Python',
        @input_data_1=@rows,
        @input_data_1_name=N'mpgcar',
        @script = N'
#modeli serileştirmek için
import pickle
import pandas as pd
import numpy as np

modelLR = pickle.loads(modelbin)
#print(modelLR)

tahminler_LR=modelLR.predict(mpgcar)
print(tahminler_LR)

gercek_tahmin_LR=np.hstack((mpgcar,tahminler_LR))

OutputDataSet=pd.DataFrame(gercek_tahmin_LR)
'
    ,@params = N'@modelbin varbinary(max)' 
    ,@modelbin = @Tmodelbin

    WITH RESULT SETS (
                (
                    cylinders int ,
                    displacement float ,
                    horsepower int ,
                    weight float ,
                    acceleration float,
                    modelyear int ,
                    origin int ,
                    mpgTahmin float
                )
            )
END

Yukarıdaki Ptyhon scriptinde pickle.loads(modelbin) satırında varbinary olarak depoladığımız eğitilmiş modeli modelLR değişkenine atadık. Artık kolayca modelLR.predict(mpgcar) satırında olduğu gibi tahmin sonuçlarını alabiliriz.

Tahmin sonuçları biz dizi olarak geliyor. Tahminleri ve tahmin için kullanılan satırları np.hstack((mpgcar,tahminler_LR)) ile birleştirip OutputDataSet değişkenine atayarak tablo formatında döndürüyoruz.

3- Tahminleri alalım:


Eğitilmiş modeli bir değişkene alalım ve yukarıda oluşturduğumuz procedureün parametrelerine ilgili değerleri vererek 4 satır için tahmin sonuçlarını görüntüleyelim.

DECLARE @trainedModel varbinary(max)
SELECT
    @trainedModel=model
FROM mpgcars_model
WHERE language='Python' and model_name='sklearn.linear_model.LinearRegression'

exec usp_PredictUsingModelBin
@Tmodelbin=@trainedModel,
@rows='SELECT * FROM (VALUES
                     (4,140,86,2790,15,82,1),
                     (4,97,67,2145,18,80,3),
                     (8,440,215,4312,8,70,1),
                     (8,455,225,3086,10,70,1)
) as t
 (cylinders,displacement,horsepower,weight,acceleration,modelyear,origin)'


Siz de farklı sayılar deneyebilirsiniz. Örneğin horsepower ve weight alanlarında değişiklik yaparak mpg (miles per galon) miktarının ne olabileceğine dair tahminleri alabilirsiniz.

Bu şekilde raw modeli deserialize edip model nesnesi elde etmek ve tahminleme yapmak hızlı olsa da çok daha hızlı yöntemler de mevcut. SQL Server tahminler üretmek için R ve Ptyhon runtimeın ihtiyaç duymayacağınız iki yöntem sunuyor. Bunlar Realtime Scoring ve Native Scoring olarak isimlendiriliyor. Bazı kısıtları olsa bu yöntemler daha hızlı.

Tabi çok daha yüksek performans ihtiyacı mevcutsa Machine Learning Service değil de Machine Learning Server ile çalışmanız daha isabetli olacaktır.

Seri boyunca uçtan uca SQL Server üzerinde Machine Learning Service in Database özelliğini kullanarak bir ML çalışmasının nasıl yapılabileceğini incelemiş olduk. Python, R, Java kodlarını kullanarak, hatta CLR entegrasyonu sayesine .NET kodlarını kullanarak SQL Server'a yeni yetenekler kazandırabilirsiniz.

faydalı olması dileğiyle...


18 Şubat 2020 Salı

SQL Server 2019 üzerinde Makine Öğrenimi - 3 (Machine Learning Services in Database (R and Python)) (ML modeli eğitmek ve depolamak)

Bu seride SQL Server 2019 özelliklerinden Machine Learning Services kullanarak R, Python scriptlerinin nasıl çalıştırıldığına ve veriyi SQL dışına çıkarmadan nasıl makine öğrenimi yapabileceğimize odaklanıyoruz. Serinin ilk yazısında özelliği tanıtıp ortamı hazırlamıştık. İkinci yazısında da Python kodları ile diskten veri okuma ve SQL tablosunu Python kodlarıyla yeniden bağlanmadan nasıl işleyebileceğimizi incelemiştik. Bu yazıya hazır olmadığınızı düşünüyorsanız. önceki yazılara bir göz atmanızı öneririm. 

Önceki yazılara ulaşmak için şu linkleri takip edebilirsiniz:


SQL Server 2019 üzerinde Makine Öğrenimi - 1 (Machine Learning Services in Database (R and Python))


SQL Server 2019 üzerinde Makine Öğrenimi - 2 (Machine Learning Services in Database (R and Python)) (Tablo ve DataFrame ile Çalışmak)

Bu yazımızda artık SQL Server Machine Learning Services özelliği sayesinde SQL Server içerisinden çıkmadan sp_execute_external_script procedureünü kullanarak Python kodlarıyla makine öğrenimini nasıl yapacağımıza odaklanabiliriz.

Bu yazının senaryosu şöyle:
  1. Önceki bölümde incelediğimiz mpgcars veri setini diskten okuyup inceleyeceğiz.
  2. Linear Regression algoritmasını, mpgcars veri setindeki bazı kolonları kullanarak mpg kolonunu tahmin etmesi için eğiteceğiz. Bu scriptleri Python kernalında test edeceğiz.
  3. Daha önce MPGCarsDB isimli veritabanı ve mpgcars isimli tablo oluşturmuştuk. Bu SQL tablosunu sp_execute_external_script'e mpgcars isimli input olarak göndereceğiz.  İkinci adımdaki scriptte gerekli düzenlemeleri yaparak sp_execute_external_script'in gövdesine alacağız. Sonrasında kolayca çalıştırmak için bu kodların tümünü başka bir procedure ile kapsülleyeceğiz.
  4. Model hakkındaki bilgileri ve eğitilmiş modeli binary formatta SQL tarafında oluşturduğumuz bir tabloya yükleyeceğiz.
Bir önceki yazıda da belirttiğim gibi hem SSMS hem de Azure Data Studio araçlarını tercih edebilirsiniz. Ben kernallar arası geçiş yapması kolay olduğu için Azure Data Studio ile ilerleyeceğim.

Azure Data Studio analiz işlemleri için bir sürü eklenti ve kolaylık sunan yeni bir araç. SQL Server 2019 kurulum dosyasından veya aşağıdaki linkten indirip kurabilirsiniz:


Senaryomuzu adım adım uygulayalım.

1. mpgcars veri setini inceleyelim:


Azure Data Tools üzerinde Python Kernalını seçiyorum ve aşağıdaki Python kodları ile mpgcars veri setini inceliyorum. Burada araştırdığım şey mpg (miles per galon) kolonu ile diğer kolonlar arasındaki ilişki. Bunun için mpgcars.corr ile kolonlar arası korelasyona bakıyorum. Büyük oranda güçlü korelasyonlar mevcut. matplotlib kütüphanesi yardımıyla da scatter grafiğinde mpg ve diğer kolonlar arası ilişki inceliyorum. 

Örneğimizde weight ile mpg kolonu arasında linear (doğrusal) bir ilişki olduğunu görmek mümkün. Diğer kolonlarda da benzer durum var. Bu durum Linear Regresyon kullanmam için beni motive ediyor. Çünkü Linear Regresyon algoritması hem basit, hem hızlı, hem de veri kümesinin uzayda bir doğru boyunca seyrettiğini varsayıyor. Bir miktar hata ile bu seyri bir doğru denklemi ile ifade etmek mümkün olacak.

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

#diskten okuyalım.
mpgcars=pd.read_csv("G:\MLinDBData\mpgcars.csv")
mpgcars=mpgcars[mpgcars["horsepower"]!="?"]

#scatter grafik oluşturalım
#plt.figure(figsize = (25, 5))
plt.scatter(mpgcars["weight"],mpgcars["mpg"])

#grafiğe ve eksenlere başlık ekleyelim
plt.title('mpg vs weight')
plt.xlabel("weight")
plt.ylabel("miles per galon")

# grafiği diske kaydedelim.
plt.savefig("G:\MLinDBData\mpg-vs-horsepower")

#korelasyon
mpgcars.corr(method ='pearson')["mpg"]


Bu arada dilerseniz plt.savefig satırında benim yaptığım gibi grafikleri bir yere kaydedebilirsiniz. Daha gelişmiş analizler yapmak mümkün. Ancak buradaki görselleştirme kütüphanelerine hakim olmanız gerekir. Eğer daha hızlı ilerlemek isterseniz Power BI Desktop uygulamasını kullanabilirsiniz. Blogda bu konuda bir çok video ve makale mevcut.

Azure Data Studio aracını kullananlar için beğendiğim bir eklentiyi önermek isterim. SandDance for Azure Studio eklentisi ile veriyi eğlenceli şekilde kum taneleriyle inceleyebilirsiniz. iki ve üç boyutlu inceleme imkanı olan bu aracı sorgu sonucunu aldığınız ekranda hemen sağda bulunan bir ikonla kullanmaya başlayabiliyorsunuz. Sonrası grafiğinizi seçmek ve eksenleri yerleştirmekten ibaret.

Eklentiyi soldaki eklentiler kısmında aratarak kurabilirsiniz:


SandDance eklentisini kurup tablonuzu sorguladıktan sonra sağ alt köşedeki ikon ile eklentiyi kullanmaya başlayabilirisiniz.



Biz mpgcars tablomuzdaki horsepower ve mpg kolonlarını scatter grafik olarak görüntüleyelim:



2. Modeli eğitelim:


Araçların özelliklerine bakarak her bir galon yakıtla ne kadar mil gideceğini tahmin edecek bir model eğiteceğiz. Linear Regresyon algoritmasını, mpg kolonunu bazı kolonlar yardımıyla tahmin edebilmek için eğitecek sonrasında başarısını test edeceğiz. Bunun için veriyi train ve test olarak ikiye ayırıyoruz. Örneğimizde %70-%30 olarak ayırdık. Algoritmayı %70'lik kısımla eğitip, eğitilmiş modelin sonucunu bildiğimiz %30'u tahmin etmesini isteyeceğiz. Model başarısını kontrol etmek için her Machine Learning problem tipine özel birtakım metrikler mevcut. Biz Regression yaptığımız için en kullanışlı metriklerden biri olan Root Mean Squared Error yani farkların karelerinin ortalamasının kare köküne bakacağız. Bu metrik test verileri ile tahminlerimiz arasında aşağı yukarı ne kadarlık sapma olduğunu bize vermiş olacak.

#y=f(X) 
# y: tahmin edilecekler yani target, X sonuçları bulmak için kullanacağımız kolonlar yani features, f ise tahmin için kullanacağımız eğitilmiş modelimiz.
#tahminde kullanılacak ve tahmin edilecek kolonları seçelim
features=["cylinders","displacement","horsepower","weight","acceleration"]
target=["mpg"]

X=mpgcars[features]
y=mpgcars[target]

#split için gerekli kütüphaneler
from sklearn.model_selection import train_test_split

#test ve train olarak veriyi ayıralım.
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.30random_state=123)

print("-----> satır, sutun sayısı")
print("X_train Satır Sutun: ",X_train.shape)
print("X_test Satır Sutun: ",X_test.shape)

#Linear Regression için gerekli kütüphane
from sklearn.linear_model import LinearRegression

#modeli eğitelim
modelLR=LinearRegression().fit(X_train,y_train)

##------Modeli Scorelayalım---------
y_tahmin=modelLR.predict(X_test)

from sklearn.metrics import mean_squared_error
import numpy as np

# Roat mean Squared Error
RMSE = np.sqrt(mean_squared_error(y_test,y_tahmin))
print("RMSE : ",RMSE)

## modeli serileştirelim. Daha sonra kullanmak üzere depolayacağız.
#modeli serileştirmek için
import pickle

modelbin=pickle.dumps(modelLR)
#print(modelbin)


Modeli oluşturduktan sonra tahminleme yapmak oldukça basit. Veri Bilimi çalışmalarının odağı doğru sorunun sorulması, problem tipinin belirlenmesi, verinin hazırlanması, sonucu etkileyecek alanların (alan, kolon, feature, domain, attribute aynı anlamdadır) seçilmesi-oluşturulması, algoritmanın seçimi, train ve test verinin seçimi, algoritma parametrelerinin optimizasyonu, sonuçların değerlendirilmesi için bir takım metrik ve grafiklerin incelenmesi, tahminlerin gerçek dünyadaki maliyetlerinin hesaplanması gibi bir çok konuyu kapsar. Çoğunlukla Veri Bilimi çalışmalarının araca, matematik-istatistik bilgisine ve probleme dair tecrübeye dayalı ön görü ve deneme yanılmanın yoğun olduğu bir süreçtir diyebiliriz. 

Biz bu yazıda SQL Server içerisinde Machine Learning çalışmalarını yapmanın mümkün olduğunu deneyimleyecek kadar konuyu ele alalım istedik. Bu konudaki detayları farklı platformlarda aktarmaktayız. Şimdilik burada oldukça yüzeysel geçiyoruz.

Linear Regresyon algoritması verileri en az hata ile ifade edecek bir doğru denklemi bulmayı hedefler. Eğitilmiş model üzerinden bu doğru denkleminin eğimini ve ekseni kestiği noktaları alabilirsiniz. Modeli eğitmeye başladığımız nokta LinearRegression().fit satırıdır. X_train ile mpg harici bazı kolonları verdik. Seçtiğimiz algoritma bu veri kümesine bakarak mpg kolonundan oluşan y_train veri setini en az hata ile ifade eden bir fonksiyon elde edecek. İşte bu fonksiyona eğitilmiş model diyoruz.

Eğitilmiş modeli modelLR.predict satırında tahminlemede kullanıyoruz. Bu sefer test verileriyle çalışarak X_test ile y_test sonuçlarını bulmaya çalışıyoruz. Sonrasında bulduğumuz y_tahmin ile y_test arasındaki sapmayı ifade eden RMSE (Root Mean Sequared Error) metriğine bakıyoruz. Burada çıkan sapma sizin için kabul edilebilir büyüklükteyse benim yaptığım gibi pickle.dumps ile modeli binary hale getirip SQL tarafında depolayabilirsiniz.

3. Kolaylık olsun diye kodları kapsülleyelim:


Yukarıdaki Python kodları ile yaptığımız çalışmayı SQL Server tarafında çalışacak hale getireceğiz. Python kodlarını sp_execute_external_script procedureünğn script parametresine olduğu gibi yapıştırabiliriz. Script içerisinde kullandığımız mpgcars veri setini SQL Server tarafından @input_data_1 ile göndereceğiz ve bu inputu @input_data_1_name parametresi ile mpgcars olarak kullanabileceğiz.

Script içerisinde eğittiğimiz modeli binary formata çevirip ve modelBin değişkenine atamıştık. Bu değişkenin tanımının scriptin altında @params parametresinde görebilirsiniz. Buradan gelen değeri en üstte tüm kodları kapsüllediğimiz procedureün @model isimli OUTPUT olarak tanımlanan parametresine ileteceğiz. sp_execute_external_script procedureünün bizim yazdığımız usp_TrainedModeBinary procedureü tarafından kapsüllendiğini gözden kaçırmayalım.

CREATE OR ALTER PROC usp_TrainedModeBinary (@model varbinary(max) OUT)
AS
BEGIN

EXEC sp_execute_external_script
             @language = N'Python',
             @input_data_1=N'SELECT mpg,cylinders,displacement,horsepower,weight,acceleration,modelyear,origin,carname FROM MPGCarsDB.dbo.mpgcars',
             @input_data_1_name=N'mpgcars',
             @script = N'
#y=f(X)
# y: tahmin edilecekler yani target, X sonuçları bulmak için kullanacağımız kolonlar yani features, f ise tahmin için kullanacağımız eğitilmiş modelimiz.
#tahminde kullanılacak ve tahmin edilecek kolonları seçelim
features=["cylinders","displacement","horsepower","weight","acceleration","modelyear","origin"]
target=["mpg"]

X=mpgcars[features]
y=mpgcars[target]

#split için gerekli kütüphaneler
from sklearn.model_selection import train_test_split

#test ve train olarak veriyi ayıralım.
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.30, random_state=123)

print("-----> satır, sutun sayısı")
print("X_train Satır Sutun: ",X_train.shape)
print("X_test Satır Sutun: ",X_test.shape)

#Linear Regression için gerekli kütüphane
from sklearn.linear_model import LinearRegression

#modeli eğitelim
modelLR=LinearRegression().fit(X_train,y_train)

##------Modeli Scorelayalım---------
y_tahmin=modelLR.predict(X_test)

from sklearn.metrics import mean_squared_error
import numpy as np

# Roat mean Squared Error
RMSE = np.sqrt(mean_squared_error(y_test,y_tahmin))
print("RMSE : ",RMSE)

## modeli serileştirelim. Daha sonra kullanmak üzere depolayacağız.
#modeli serileştirmek için
import pickle

modelbin=pickle.dumps(modelLR)
#print(modelbin)
'
             ,@params = N'@modelbin varbinary(max) OUTPUT'
             ,@modelbin = @model OUTPUT
END

4. Scriptten gelen binary modeli bir SQL Server tablosuna kaydedelim:


Eğitilmiş modeli kaydedelim ki sahada kullanırken tekrar tekrar modeli eğitmek durumunda kalmayalım. Modeli eğitmek uzun süre bir işlem olduğu için her tahminden önce bunu yapmak mümkün olmayabilir. Model eğitme işlemi yavaş olduğu için aralıklarla yapılır ve  başarılı bir fonksiyon haline gelmiş eğitilen model tahminlemelerde kullanılmak üzere depolanır. 

Biz bu modeli şimdi oluşturacağımız tabloda binary olarak depolayalım. Böylece daha sonra tahminlemede kullanmak üzere serileştirip model nesnesi haline getirebiliriz.

--mpg eğitilmiş modelin saklanacağı tablo
CREATE TABLE mpgcars_model
(
       language nvarchar(20),
       model_name nvarchar(50),
       model varbinary(max),
       model_date datetime DEFAULT(GETDATE())
)
GO

--modeli alalım.
DECLARE @TrainedModel varbinary(max)

exec usp_TrainedModeBinary @model=@TrainedModel OUT

--select @m
INSERT INTO mpgcars_model(language,model_name,model,model_date) VALUES('Python','sklearn.linear_model.LinearRegression',@TrainedModel,GETDATE())

--TRUNCATE TABLE mpgcars_model
select * from mpgcars_model


Bu yazıda özellikleri verilen bir aracın mpg değerini tahmin edebilecek bir model eğittik. Bu modeli binary olarak SQL Server tablosunda depoladık. Sonraki yazımızda bu modeli serileştirip model nesnesi elde edeceğiz. Elde ettiğimiz bu model nesnesiyle tahminleme yapabileceğiz.

faydalı olması dileğiyle...