原帖地址:https://d-bi.gitee.io/sqlserver-ml-services/
新年第一篇,去舊迎新。本文內容,既舊也新。舊之處在於,SQL Server 機器學習服務是微軟在SQL Server 2016 中就引入的新功能,但當時只支持R語言,所以也稱為”R Server”,在SQL Server 2017及后續版本中,提供了對Python的支持,因此,現稱為”Machine Learning Services(機器學習服務)”的功能自發布至今為止已有兩年多的時間,故而這並不算一個新功能。而新的地方在於,此功能自發布起國內資料極少,一方面使用較舊版本SQL Server的用戶依然很多,另一方面是很多人對該功能缺乏了解,然而,機器學習算法可以對數據進行深度挖掘,這對企業BI智能化的意義非常大,將AI融入BI也是企業未來實現商業智能的大方向。
本文將首先講述機器學習服務(以Python為例)的概念,意義以及其基本應用原理,簡單講講它的安裝和部署方面的相關問題,最后會提供一個教程講解其具體的應用方法。
什么是機器學習服務?
機器學習服務是SQL Server中提供的一項新特性,它允許用戶可以在SQL Server中,使用存儲過程調用R或Python腳本處理數據, 訓練和部署機器學習模型。通俗地說,SQL Server數據庫的數據可以直接傳遞至Python中進行處理和建模,Python處理好后可以將結果返回到SQL Server數據庫(下文會進一步講述這點),此方式使SQL Server集成了Python在數據處理和機器學習算法方面的強大功能,且這一切操作均在SQL Server內部完成(因此這也不同於獨立版本的SQL Server機器學習服務器)。
(注:SQL Server 2019還提供了對Java支持,但不屬於機器學習服務,在此忽略)
為何要使用機器學習服務?
到此處,部分讀者可能會問,即使不使用機器學習服務,Python依然可以利用一些庫(如sqlalchemy)來實現從數據庫中獲取和寫回數據(如此文),依然可以利用Python強大的算法庫預測數據並將結果寫回數據庫,那為何還要使用機器學習服務呢?事實上,這是不同的,因為利用SQL Server機器學習服務,能夠帶來如下優勢:
- 可重復利用性。執行包含Python腳本的存儲過程訓練出的模型可以進行序列化,以單個值的形式存儲在實體表中,只要模型調試好就可以在以后需要時重復利用。比如你可以提供給其他應用程序(如SSIS) 或其他的存儲過程繼續調用,部署到生產環境中,定期執行數據挖掘。
- 拓展性。SQL Server 機器學習服務使用Anaconda發行版,內置豐富的Python庫,還可以安裝第三方框架,如 TensorFlow和scikit-learn。
- 安全性。此功能在數據所在的位置運行腳本,無需通過網絡將數據傳輸到其他服務器。通過在 SQL Server 管理的安全框架內執行受信任的腳本語言,數據庫管理員可以在維持安全性的同時允許數據挖掘工程師訪問企業數據。
- 可監控性。可以在SSMS中使用由微軟提供或自行設計的報表監視Python的執行情況(關於安裝此報表)。
- 與BI工具集成。存儲過程中的參數值可以傳遞至Python,這意味着在使用SSRS(或Power BI Report Builder) 構建的報表中,用戶可以直接調整機器學習算法中的參數,將算法模型的調優及結果的呈現自動化。比如使用多元線性回歸預測銷售數據,通過調整模型中不同的參數來優化模型(對於此,如果你使用Power BI, 此文提供了使用DAX建模及調優的用例)
(若針對於R語言,還有一個優勢是可以以多線程的方式執行R腳本,而Python本身就支持多線程)
機器學習服務的運行原理
在SQL Server中安裝了機器學習服務后,在SQL Server 配置管理器中會出現一個名為”SQL Server Launchpad”的服務,此即為SQL Server用於執行外部腳本(Python或R)的服務,官方提供的運行流程如下圖所示,在此不一一贅述,詳情可參考此文檔:
(注:關於revoscalepy, 這是一個由微軟開發的Python機器學習庫,它提供了一些常用的機器學習算法,如決策樹,線性回歸以及Logistic回歸等),支持分布和遠程計算環境,詳見文檔)
關於安裝與部署
在SQL Server中訓練並部署Python模型需要SQL Server至少在2017及以上版本,在Windows和Linux上都可以安裝機器學習服務。關於安裝與部署,我會在下文提供幾個十分有用的鏈接來幫助你順利的在SQL Server安裝機器學習服務器。
(如果你需要下載全新的SQL Server可點此到達下載頁面)
安裝此功能,你需要打開SQL Server Installation Center,進入安裝向導,添加Machine Learning Services及Python兩項功能,你可以參考官方文檔了解詳細的安裝過程。如果你在安裝過程中遇到問題導致安裝失敗,你可以參考此文檔,該文檔詳細列出出了可能遇到的問題以及解決建議。離線安裝機器學習服務參考此文檔,在該文檔提到你需要下載兩個CAB文件放置在你的安裝根目錄中:
如果你的SQL Server不是初始版本(RTM),那么在安裝過程中需要提供的兩個CAB文件需要和你的SQL Server具體版本相對應(查SQL Server具體版本的命令:SELECT @@VERSION),此頁面提供了完整的SQL Server累計更新中各版本對應的CAB文件下載的下載地址。
(注:對於簡體中文版需要將CAB文件后綴名由1033改為2052,否則安裝程序會找不到CAB文件從而導致報錯)
安裝成功后,可以嘗試運行較簡單的Python腳本作為測試,此文檔提供了一個很好的入門教程,可以讓你慢慢熟悉使用存儲過程來調用Python的方法。
如何使用機器學習服務訓練預測模型(Python)
典型的流程是,打開SSMS,先創建一個包含Python建模代碼的存儲過程,執行該存儲過程將模型以單條記錄保存在一張實體表,然后第二個存儲過程從該表中獲取該記錄,調用該模型為新數據生成預測(回歸或分類),並將結果返回到新的實體表中。
(提示:建議先使用Python IDE完成Pyhon腳本,一個好的建議是打開機器學習服務安裝根目錄,打開jupyter-notebook.exe,使用jupyter notebook測試Python腳本)
以下案例是我以紅酒質量數據集為例,使用70%的數據作為訓練數據,30%的數據作為測試數據,使用隨機森林算法預測紅酒的質量等級。具體步驟如下:
1.創建一個存儲過程—用於訓練數據集以生成預測模型
(其中:@input_data_參數用於獲取數據集)
DROP PROCEDURE IF EXISTS generate_model_rfc; go CREATE PROCEDURE generate_model_rfc (@trained_model varbinary(max) OUTPUT) AS BEGIN EXECUTE sp_execute_external_script @language = N'Python' , @script = N' import numpy as np import pandas as pd import pickle from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn import metrics dt = train_data dt["Level"] = dt["Level"].astype(''category'') X = dt[["Fixed Acidity","Volatile Acidity","Citric acid","Residual Sugar","Chlorides","Free Sulfur Dioxide","Total Sulfur Dioxide","Density","PH","Sulphates","Alcohol"]] Y = dt[["Level"]] X_Train, X_Test, Y_Train, Y_Test = train_test_split(X, Y, test_size=0.3, random_state=42) RFC=RandomForestClassifier(n_estimators=100,criterion=''gini'',min_samples_split=2,max_depth=2) RFC.fit(X_Train,Y_Train.values.ravel()) trained_model = pickle.dumps(RFC) ' , @input_data_1 = N'select "Fixed Acidity", "Volatile Acidity", "Citric acid", "Residual Sugar", "Chlorides", "Free Sulfur Dioxide", "Total Sulfur Dioxide", "Density", "PH", "Sulphates", "Alcohol", "Level" from dbo.RedWineQuality' , @input_data_1_name = N'train_data' , @params = N'@trained_model varbinary(max) OUTPUT' , @trained_model = @trained_model OUTPUT; END; GO
2.創建一個表–用於存儲預測模型
CREATE TABLE dbo.my_py_models ( model_name VARCHAR(50) NOT NULL DEFAULT('default model') PRIMARY KEY, model_object VARBINARY(MAX) NOT NULL ); GO
3.執行第一個存儲過程–生成預測模型並存儲在上述創建的表(my_py_models)中
DECLARE @model_object VARBINARY(MAX); EXEC generate_model_rfc @model_object OUTPUT; INSERT INTO my_py_models (model_name, model_object) VALUES('RandomForestClassification(RFC)', @model_object);
4.創建第二個存儲過程–用於調用現有預測模型對新增數據進行預測
本案例的訓練數據集和測試數據集是在Python腳本之中使用train_test_split進行拆分,而官方文檔的案例與此不同,訓練數據集和測試數據集使用WHERE拆分,先后作為參數傳遞給兩個存儲過程的Python腳本,因此本案例無論是generate_model_rfc(第一個存儲過程)還是py_predict_rfc,@input_data_1參數都是一樣的。因此本案例對於不便使用WHERE拆分的數據集有一定參考性,在此注意兩次拆分都需要指定相同的隨機種子(如此處:random_state=42)
DROP PROCEDURE IF EXISTS py_predict_rfc; GO CREATE PROCEDURE py_predict_rfc (@model varchar(100)) AS BEGIN DECLARE @py_model varbinary(max) = (select model_object from dbo.my_py_models where model_name = @model); EXEC sp_execute_external_script @language = N'Python', @script = N' import pickle import numpy as np import pandas as pd from sklearn.model_selection import train_test_split py_model_rfc = pickle.loads(py_model) dt = data dt["Level"] = dt["Level"].astype(''category'') X = dt[["Fixed Acidity","Volatile Acidity","Citric acid","Residual Sugar","Chlorides","Free Sulfur Dioxide","Total Sulfur Dioxide","Density","PH","Sulphates","Alcohol"]] Y = dt[["Level"]] X_Train, X_Test, Y_Train, Y_Test = train_test_split(X, Y, test_size=0.3, random_state=42) Predictions = py_model_rfc.predict(X_Test) OutputDataSet=pd.DataFrame(data=Predictions,columns=[''Prediction'']) OutputDataSet[''Actual''] = pd.Series(Y_Test[''Level''].values,index=np.arange(0,len(Y_Test))) ' , @input_data_1 = N'select "Fixed Acidity", "Volatile Acidity", "Citric acid", "Residual Sugar", "Chlorides", "Free Sulfur Dioxide", "Total Sulfur Dioxide", "Density", "PH", "Sulphates", "Alcohol", "Level" from dbo.RedWineQuality' , @input_data_1_name = N'data' , @params = N'@py_model varbinary(max)' , @py_model = @py_model with result sets (("Prediction" int, "Actual" int)); END; GO
5.創建一個新表–用於存儲模型測試結果
CREATE TABLE [dbo].[py_rfc_predictions]( [Prediction] int, [Actual] int )
6.執行第二個存儲過程–預測數據並將結果輸出到上述新表(py_rfc_predictions)中
如前述代碼所示,該表返回是一個僅有兩個字段的驗證表,一列存放預測的數據–[Prediction],一列是真實的數據–[Actual]。
INSERT INTO py_rfc_predictions EXEC py_predict_rfc 'RandomForestClassification(RFC)'; SELECT * FROM py_rfc_predictions;
至此,即是機器學習模型訓練與使用的完整流程。
總結
SQL Server和Python的強強聯手,能夠使報表開發者更好地獲取到經過機器學習算法生成的深度挖掘的數據,這類數據往往難以使用前端的BI工具完成,比如在Power BI中,利用DAX只能實現簡單基礎的算法(如用DAX實現KNN分類算法),在Power BI Premium以及Power BI Embedded中雖然具備機器學習功能但只支持雲端版本,且這種機器學習模型的訓練相比用戶自己根據自身需求直接使用Python代碼訓練的方式而言,無論是可選擇性還是效果等等,都有很明顯的差距。顯然在企業環境中,使用機器學習服務挖掘數據並存儲在數據庫,然后使用前端BI工具直接讀取結果集是更規范更實用的辦法。
本作品采用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。