如何使用 SQL 對數據進行分析?

如何使用 SQL 對數據進行分析?

在這裏插入圖片描述

前言

我們通過 OLTP(聯機事務處理)系統實時處理用戶數據,還需要在 OLAP(聯機分析處理)系統中對它們進行分析,今天我們來看下如何使用 SQL 分析數據。

使用 SQL 進行數據分析的幾種方式

在 DBMS(數據庫管理系統) 中,有些數據庫很好地集成了 BI 工具,可以方便我們對收集的數據進行商業分析。
比如在SQL Server 中提供了 BI 分析工具,我們可以通過使用 SQL Server中的 Analysis Services 完成數據挖掘任務。SQL Server 內置了多種數據挖掘算法,比如常用的 EM、K-Means 聚類算法、決策樹、樸素貝葉斯和邏輯迴歸等分類算法,以及神經網絡等模型。我們還可以對這些算法模型進行可視化效果呈現,幫我們優化和評估算法模型的好壞。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-uxDqBJLM-1592728193777)(media/15777852880253/15778092138631.jpg)]

圖片來源::https://docs.microsoft.com/en-us/analysis-services/analysis-services-features-supported-by-the-editions-of-sql-server-2016

另外 PostgreSQL 是一個免費開源的關係數據庫(ORDBMS),它的穩定性非常強,功能強大,在 OLTP 和 OLAP 系統上表現都非常出色。同時在機器學習上,配合 Madlib 項目可以讓 PostgreSQL 如虎添翼。Madlib 包括了多種機器學習算法,比如分類、聚類、文本分析、迴歸分析、關聯規則挖掘和驗證分析等功能。這樣我們可以通過使用 SQL,在 PostgreSQL 中使用各種機器學習算法模型,幫我們進行數據挖掘和分析。
在這裏插入圖片描述
圖片來源:https://cwiki.apache.org/confluence/display/MADLIB/Architecture

2018 年 Google 將機器學習(Machine Learning)工具集成到了 BigQuery 中,發佈了 BigQuery ML,這樣開發者就可以在大型的結構化或半結構化的數據集上構建和使用機器學習模型。通過 BigQuery 控制檯,開發者可以像使用 SQL 語句一樣來完成機器學習模型的訓練和預測。
在這裏插入圖片描述
SQLFlow 是螞蟻金服於 2019 年開源的機器學習工具,我們可以通過使用 SQL 就可以完成機器學習算法的調用,你可以將 SQLFlow 理解爲機器學習的翻譯器。我們在 SELECT 之後加上 TRAIN 從句就可以完成機器學習模型的訓練,在 SELECT 語句之後加上 PREDICT 就可以使用模型來進行預測。這些算法模型既包括了傳統的機器學習模型,也包括了基於 Tensorflow、PyTorch 等框架的深度學習模型。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-mvW765Gb-1592728193780)(media/15777852880253/15778199737535.jpg)]
從上圖中你能看出 SQLFlow 的使用過程,首先我們可以通過 Jupyter notebook 來完成 SQL 語句的交互。SQLFlow 支持了多種 SQL 引擎,包括 MySQL、Oracle、Hive、SparkSQL 和 Flink 等,這樣我們就可以通過 SQL 語句從這些 DBMS 數據庫中抽取數據,然後選擇想要進行的機器學習算法(包括傳統機器學習和深度學習模型)進行訓練和預測。不過這個工具剛剛上線,工具、文檔、社區還有很多需要完善的地方。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-OLLLDijn-1592728193782)(media/15777852880253/15778543875466.jpg)]

最後一個最常用方法是 SQL+Python,也是我們今天要重點講解的內容。上面介紹的工具可以說既是 SQL 查詢數據的入口,也是數據分析、機器學習的入口。不過這些模塊耦合度高,也可能存在使用的問題。一方面工具會很大,比如在安裝 SQLFlow 的時候,採用 Docker 方式進行安裝,整體需要下載的文件會超過 2G。同時,在進行算法調參、優化的時候也存在靈活度差的情況。因此最直接的方式,還是將 SQL 與數據分析模塊分開,採用 SQL 讀取數據,然後通過 Python 來進行數據分析的處理。

案例:挖掘購物數據中的頻繁項集與關聯規則

下面我們通過一個案例來進行具體的講解。

我們要分析的是購物問題,採用的技術爲關聯分析。它可以幫我們在大量的數據集中找到商品之間的關聯關係,從而挖掘出經常被人們購買的商品組合,一個經典的例子就是“啤酒和尿布”的例子。

今天我們的數據集來自於一個購物樣本數據,字段包括了 trans_id(交易 ID)以及 product(商品名稱),具體的數據集參考下面的初始化 sql:

DROP TABLE IF EXISTS test_data;
CREATE TABLE test_data (
    trans_id INT,
    product TEXT
);
INSERT INTO test_data VALUES (1, 'beer');
INSERT INTO test_data VALUES (1, 'diapers');
INSERT INTO test_data VALUES (1, 'chips');
INSERT INTO test_data VALUES (2, 'beer');
INSERT INTO test_data VALUES (2, 'diapers');
INSERT INTO test_data VALUES (3, 'beer');
INSERT INTO test_data VALUES (3, 'diapers');
INSERT INTO test_data VALUES (4, 'beer');
INSERT INTO test_data VALUES (4, 'chips');
INSERT INTO test_data VALUES (5, 'beer');
INSERT INTO test_data VALUES (6, 'beer');
INSERT INTO test_data VALUES (6, 'diapers');
INSERT INTO test_data VALUES (6, 'chips');
INSERT INTO test_data VALUES (7, 'beer');
INSERT INTO test_data VALUES (7, 'diapers');

這裏我們採用的關聯分析算法是 Apriori 算法,它幫我們查找頻繁項集,首先我們需要先明白什麼是頻繁項集。

頻繁項集就是支持度大於等於最小支持度閾值的項集,小於這個最小值支持度的項目就是非頻繁項集,而大於等於最小支持度的項集就是頻繁項集。支持度是個百分比,指的是某個商品組合出現的次數與總次數之間的比例。支持度越高,代表這個組合出現的頻率越大。

我們再來看下 Apriori 算法的基本原理。

Apriori 算法其實就是查找頻繁項集 (frequent itemset) 的過程:
0.設置一個最小支持度,
1.從K=1開始,篩選頻繁項集。
2.在結果中,組合K+1項集,再次篩選
3.循環1、2步。直到找不到結果爲止,K-1項集的結果就是最終結果。

我們來看下數據理解一下,下面是所有的訂單,以及每筆訂單購買的商品:

訂單編號 購買的商品
1 beer(啤酒)、diapers(尿布)、chips(薯條)
2 beer(啤酒)、diapers(尿布)
3 beer(啤酒)、diapers(尿布)
4 beer(啤酒)、chips(薯條)
5 beer(啤酒)
6 beer(啤酒)、diapers(尿布)、chips(薯條)
7 beer(啤酒)、diapers(尿布)

在這個例子中,“啤酒”出現了 7 次,那麼這 7 筆訂單中“牛奶”的支持度就是 7/7=1。同樣“啤酒 + 尿布”出現了 5 次,那麼這 7 筆訂單中的支持度就是 5/7=0.71

同時,我們還需要理解一個概念叫做“置信度”,它表示的是當你購買了商品 A,會有多大的概率購買商品 B,在這個例子中,置信度(啤酒→尿布)=5/7=0.71,代表如果你購買了啤酒,會有 71% 的概率會購買尿布;置信度(啤酒→薯條)=3/7=0.43,代表如果你購買了啤酒,有 43% 的概率會購買薯條。

所以說置信度是個條件概念,指的是在 A 發生的情況下,B 發生的概率是多少。

我們在計算關聯關係的時候,往往需要規定最小支持度和最小置信度,這樣纔可以尋找大於等於最小支持度的頻繁項集,以及在頻繁項集的基礎上,大於等於最小置信度的關聯規則。

使用 MADlib+PostgreSQL 完成購物數據的關聯分析

針對上面的購物數據關聯分析的案例我們可以使用工具自帶的關聯規則進行分析,下面我們演示使用 PostgreSQL 數據庫在 Madlib 工具中都可以找到相應的關聯規則,通過寫 SQL 的方式就可以完成關聯規則的調用分析。

開發環境

  • Windows/MacOS
  • Navicat Premium 11.2.7及以上

服務器環境

  • Centos 7.6
  • Docker
  • PostgreSQL 9.6
  • MADlib 1.4及以上

使用 Docker 安裝 MADlib+PostgreSQL

拉取 docker 鏡像(這個鏡像提供了需要的 postgres 等環境,並沒有安裝 madlib) :

docker pull madlib/postgres_9.6:latest

下載 MADlib github 源碼. 假定下載的源碼位置爲 /home/git-repo/github/madlib

cd /home/git-repo/github && git clone [email protected]:apache/madlib.git

啓動容器,並建立本機目錄與容器中系統的路徑映射,共享的目錄在容器和本機之間是讀寫共享的。

docker run -d -it --name madlib -v /home/git-repo/github/madlib:/incubator-madlib/ madlib/postgres_9.6

啓動容器後,連接容器編譯 MADlib 組件,編譯用時約 30 分鐘:

docker exec -it madlib bash
mkdir /incubator-madlib/build-docker
cd /incubator-madlib/build-docker
cmake ..
make
make doc
make install

在容器中安裝 MADlib:

src/bin/madpack -p postgres -c postgres/postgres@localhost:5432/postgres install

運行 MADlib 測試:

# Run install check, on all modules:
src/bin/madpack -p postgres -c postgres/postgres@localhost:5432/postgres install-check

# Run install check, on a specific module, say svm:
src/bin/madpack -p postgres -c postgres/postgres@localhost:5432/postgres install-check -t svm

# Run dev check, on all modules (more comprehensive than install check):
src/bin/madpack -p postgres -c postgres/postgres@localhost:5432/postgres dev-check

# Run dev check, on a specific module, say svm:
src/bin/madpack -p postgres -c postgres/postgres@localhost:5432/postgres dev-check -t svm

# 如果需要,重新安裝 Reinstall MADlib:
src/bin/madpack -p postgres -c postgres/postgres@localhost:5432/postgres reinstall

如果需要,先關掉並刪除容器,刪完再起新容器需要重新安裝:

docker kill madlib
docker rm madlib

用配置好的容器製作新鏡像,先查看容器 ID, 在用容器 ID 創建新鏡像:

docker ps -a
docker commit <container id> my/madlib_pg9.6_dev

用新鏡像創建新容器:

docker run -d -it -p 5432:5432 --name madlib_dev -v /home/my/git-repo/github/madlib:/incubator-madlib/ madlib/postgres_9.6 

連接容器進行交互(發現新容器還是沒有安裝,但是不用編譯了,安裝也很快,裝完測試一下)

docker exec -it madlib_dev bash
cd  /incubator-madlib/build-docker
src/bin/madpack -p postgres -c postgres/postgres@localhost:5432/postgres install
src/bin/madpack -p postgres -c postgres/postgres@localhost:5432/postgres install-check

使用 Navicat 遠程連接 PostgreSQL(假定沒有修改登錄用戶和密碼,默認沒有密碼)

最後,新建表並初始化數據:
在這裏插入圖片描述

使用 SQL 完成關聯規則的調用分析

最後使用 SQL + MADlib 進行關聯分析,這裏我們設定了參數最小支持度爲 0.25,最小置信度爲 0.5。根據條件生成 transactions 中的關聯規則,如下所示:

SELECT * FROM madlib.assoc_rules( .25,            -- 支持度
                                  .5,             -- 置信度
                                  'trans_id',     -- Transaction id 字段
                                  'product',      -- Product 字段
                                  'test_data',    -- 輸入數據
                                  NULL,           -- 輸出模式
                                  TRUE            -- 詳細輸出
                                );

查詢結果:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-0TlxsX0M-1592728193789)(media/15777852880253/15778524671785.jpg)]
關聯規則存儲在 assoc_rules 表中:

SELECT * FROM assoc_rules
ORDER BY support DESC, confidence DESC;

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-FRk74l6h-1592728193790)(media/15777852880253/15778525462568.jpg)]

注意:
關聯規則會始終創建一個名爲的表 assoc_rules。如果要保留多個關聯規則表,請在再次運行之前複製該表。

使用 SQL+Python 完成購物數據的關聯分析

除此以外,我們還可以直接使用 SQL 完成數據的查詢,然後通過 Python 的機器學習工具包完成關聯分析。

開發環境

  • Windows/MacOS
  • Navicat Premium 11.2.7及以上
  • Python 3.6

服務器環境

  • Centos 7.6
  • Docker
  • MySQL 5.7

使用 Docker 安裝 MySQL

拉取官方鏡像(我們這裏選擇5.7,如果不寫後面的版本號則會自動拉取最新版):

docker pull mysql:5.7

檢查是否拉取成功:

docker images
REPOSITORY                        TAG                 IMAGE ID            CREATED             SIZE
docker.io/mysql                   5.7                 db39680b63ac        2 days ago          437 MB

啓動容器:

docker run -p 3306:3306 --name mymysql -v $PWD/conf:/etc/mysql/conf.d -v $PWD/logs:/logs -v $PWD/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
  • –name:容器名,此處命名爲 mymysql;
  • -e:配置信息,此處配置 mysql 的 root 用戶的登陸密碼;
  • -p:端口映射,此處映射 主機 3306 端口到容器的 3306 端口;
  • -d:源鏡像名,此處爲 mysql:5.7;
  • -v:主機和容器的目錄映射關係,":"前爲主機目錄,之後爲容器目錄。

檢查容器是否正常運行:

[root@VM_0_10_centos ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
d1e682cfdf76        mysql:5.7           "docker-entrypoint..."   14 seconds ago      Up 13 seconds       0.0.0.0:3306->3306/tcp, 33060/tcp   mymysql

可以看到容器 ID、容器的源鏡像、啓動命令、創建時間、狀態、端口映射信息、容器名字。

進入 docker 本地連接 MySQL 客戶端:

sudo docker exec -it mymysql bash
mysql -u root -p 

設置遠程訪問賬號,並授權遠程連接:

CREATE USER 'zuozewei'@'%' IDENTIFIED WITH mysql_native_password BY 'zuozewei';
GRANT ALL PRIVILEGES ON *.* TO 'zuozewei'@'%';       

使用 Navicat 遠程連接 MySQL,新建數據庫並初始化數據。

編寫 Python 腳本完成數據分析

首先我們通過 SQLAlchemy 來完成 SQL 查詢,使用 efficient_apriori 工具包的 Apriori 算法。
整個工程一共包括 3 個部分:

  • 第一個部分爲數據加載,首先我們通過 sql.create_engine 創建 SQL 連接,然後從數據集表中讀取全部的數據加載到 data 中。這裏需要配置 MySQL 賬戶名和密碼;
  • 第二步爲數據預處理。我們還需要得到一個 transactions 數組,裏面包括了每筆訂單的信息,其中每筆訂單是以集合的形式進行存儲的,這樣相同的訂單中 item 就不存在重複的情況,同時也可以使用 Apriori 工具包直接進行計算;
  • 最後一步,使用 Apriori 工具包進行關聯分析,這裏我們設定了參數 min_support=0.25,min_confidence=0.5,也就是最小支持度爲 0.25,最小置信度爲 0.5。根據條件找出 transactions 中的頻繁項集 itemsets 和關聯規則 rules。

下載依賴庫:

#pip3 install 包名 -i 源的url 臨時換源
#清華大學源:https://pypi.tuna.tsinghua.edu.cn/simple/

# 強大的數據結構庫,用於數據分析,時間序列和統計等
pip3 install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple/ 

# python的orm程序
pip3 install SQLAlchemy -i https://pypi.tuna.tsinghua.edu.cn/simple/ 

# Apriori算法的高效純Python實現
pip3 install efficient-apriori -i https://pypi.tuna.tsinghua.edu.cn/simple/ 

# MySQL驅動
pip3 install mysql-connector -i https://pypi.tuna.tsinghua.edu.cn/simple/ 

具體的代碼如下:

from efficient_apriori import apriori
import sqlalchemy as sql
import pandas as pd

'''
數據加載
'''

# 創建數據庫連接
engine = sql.create_engine('mysql+mysqlconnector://zuozewei:zuozewei@server_ip/SQLApriori')
# 查詢數據
query = 'SELECT * FROM test_data'
# 加載到 data 中
data = pd.read_sql_query(query, engine)

'''
數據預處理
'''

# 得到一維數組 orders_series,並且將 Transaction 作爲 index, value 爲 Item 取值
orders_series = data.set_index('trans_id')['product']
# 將數據集進行格式轉換
transactions = []
temp_index = 0
for i, v in orders_series.items():
	if i != temp_index:
		temp_set = set()
		temp_index = i
		temp_set.add(v)
		transactions.append(temp_set)
	else:
		temp_set.add(v)

'''
數據分析
'''

# 挖掘頻繁項集和頻繁規則
itemsets, rules = apriori(transactions, min_support=0.25,  min_confidence=0.5)

print('頻繁項集:', itemsets)
print('關聯規則:', rules)

運行結果:

頻繁項集: {
1: {('beer',): 7, ('chips',): 3, ('diapers',): 5}, 
2: {('beer', 'chips'): 3, ('beer', 'diapers'): 5, ('chips', 'diapers'): 2}, 
3: {('beer', 'chips', 'diapers'): 2}
}

關聯規則: [
{chips} -> {beer}, 
{diapers} -> {beer}, 
{beer} -> {diapers}, 
{chips} -> {diapers}, 
{chips, diapers} -> {beer}, 
{beer, chips} -> {diapers}, 
{chips} -> {beer, diapers}
]

從結果中我們能看到購物組合中:

  • 商品個數爲 1 的頻繁項集有 3 種,分別爲 beer(啤酒)、chips(薯條)、diapers(尿布) 等;
  • 商品個數爲 2 的頻繁項集有 3 種,包括{beer(啤酒), chips(薯條)},{beer(啤酒), diapers(尿布)},{chips(薯條), diapers(尿布)}等;
  • 其中關聯規則有 7 種,包括了購買 chips(薯條) 的人也會購買 beer(啤酒),購買 diapers(尿布)的同時也會 beer(啤酒) 等。

總結

通過 SQL 完成數據分析、機器學習還是推薦使用到 Python,因爲這是 Python 所擅長的。通過今天的例子我們應該能看到採用 SQL 作爲數據查詢和分析的入口是一種數據全棧的思路,對於數據開發人員來說降低了數據分析的技術門檻。相信在當今的 DT 時代,我們的業務增長會越來越依靠於 SQL 引擎 + AI 引擎

參考文獻:
[1]:http://madlib.apache.org/docs/latest/group__grp__assoc__rules.html
[2]:https://sql-machine-learning.github.io/
[3]:https://www.jianshu.com/p/8e1e64c08cb7
[4]:數據分析實戰45講-陳暘-清華大學計算機博士

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章