1. 程式人生 > 其它 >kmeans演算法中的sse_在PostgreSQL裡進行機器學習:KMEANS 聚類嘗試

kmeans演算法中的sse_在PostgreSQL裡進行機器學習:KMEANS 聚類嘗試

技術標籤:kmeans演算法中的sse

10行解釋機器學習

每個閱讀報紙,雜誌或任何其他普遍感興趣的媒體的人至少都對機器學習的基本概念有所瞭解。機器學習不僅僅是一種時尚,它更成為我們日常生活的一部分,並且將來會更多:從網際網路上的個性化廣告到機器人牙醫或自動駕駛汽車,機器學習似乎成為一切事物的某種超能力。

但是,什麼是機器學習呢?它主要是一組統計演算法,基於現有資料,能夠從中獲得洞察力。這些演算法基本上分為兩個系列,監督學習和非監督學習。在監督學習中,目標是執行某種預測,例如,電子郵件是否是垃圾郵件(分類),下週將在超市中銷售多少啤酒(迴歸)等等,相反地,無監督學習側重於回答我的案例如何分組的問題?這些演算法的作用(每個演算法都有其特殊性)是儘可能使相似的事物儘可能接近,不同的事物則儘可能地遠離。

機器學習的普及化徹底改變了我們開展業務的方式。無論您是在談論10或10,000名員工,如果您沒有利用您的資料做出決策,那麼您肯定會落後於您的競爭對手。

不離開資料庫就可以進行機器學習

關係資料庫絕對是資料永續性最重要的工具。雖然還有其他替代方案可能適用於某些目的,但可能沒有至少具有最小IT基礎架構的公司沒有資料庫。

因此,如果每個公司都有一個數據庫,它包含值得使用的資料。這意味著每家公司都有機會通過使用機器學習以最小的努力改進其決策過程。但是,他的缺點是,對於大多數DBMS,您需要在資料庫之外執行機器學習過程。但對PostgreSQL來說並不是這樣。

由於PostgreSQL包含對其他語言的多個擴充套件,您可以在不離開PostgreSQL的情況下訓練和使用您的機器學習演算法(MadLib也是不錯的選擇,不過對平臺比較挑剔)。

讓我們看一下如何使用PLPython直接在PostgreSQL中進行Kmeans聚類,這是最流行的無監督學習演算法之一。

PostgreSQL中逐步實現KMeans

1. 載入資料樣例

本示例,我們將使用知名的鳶尾花資料,首先我們下載資料(https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data)到本地。

接下建立iris 表:

CREATE TABLE iris(sepal_lengthREAL,sepal_width REAL,petal_length REAL,petal_width REAL,species varchar(20));

表建立完畢,我們就可以匯入剛下載的資料了,在執行下面命令前,記得刪除iris.data最後的空行,

COPY iris FROM '/path/to/iris.data' DELIMITER ',';

資料準備完畢,接下來可以進入到KMeans的核心函式環節了。

2. 安裝依賴

  1. Python:目前有兩個主要的版本,2.7和3.7。PostgreSQL預設支援Python 2,你可以根據需要選擇Python 3。

  2. PL/Python:對應Python 2和Python 3,也有兩個版本的plpython,分別是plpython2u和plpython3u,你可以選擇一個,或者同時安裝。

  3. 安裝額外的Python元件:使用你喜歡的Python包管理器(pip,conda等等)來安裝scikit-learn和pandas。順便說下,如果你想使用Python進行機器學習,這兩個包都是必須的。

pip install sklearn pandas

安裝好之後就可以建立外掛了。

CREATEEXTENSIONplpythonu

3. PostgreSQL裡的Kmeans

用PL/Python編寫的函式可以像任何其他SQL函式一樣呼叫。由於Python擁有無盡的機器學習庫,因此整合非常簡單。此外,除了完全支援Python之外,PL/Python還提供了一組便捷函式來執行任何引數化查詢。因此,執行機器學習演算法可能只是幾行程式碼的問題。讓我們來看看吧。

CREATE OR replace FUNCTION kmeans(input_table text, columns text[], clus_num int) RETURNS bytea AS$$from pandas import DataFramefrom sklearn.cluster import KMeansfromcPickleimportdumpsall_columns = ",".join(columns)if all_columns == "":all_columns="*"rv = plpy.execute('SELECT %s FROM %s;' % (all_columns, plpy.quote_ident(input_table))) frame = [] for i in rv:    frame.append(i)df = DataFrame(frame).convert_objects(convert_numeric =True)kmeans = KMeans(n_clusters=clus_num, random_state=0).fit(df._get_numeric_data())return dumps(kmeans) $$ LANGUAGE plpythonu;

如您所見,指令碼非常簡單。首先,我們匯入我們需要的函式,然後我們從傳遞的列生成一個字串,或者用*替換它,如果傳遞一個空陣列,最後我們使用PL/Python的執行函式構建查詢。雖然它超出了本文的範圍,但我強烈建議閱讀有關如何使用PL/Python引數化查詢的內容。

一旦構建並執行了查詢,我們需要將其轉換為將其轉換為資料框並將數值變數轉換為數字型別(預設情況下,它們可能會被解釋為其他內容)。然後,我們呼叫kmeans,其中傳遞的輸入組數量作為引數傳遞,作為您想要獲取的聚類數量。最後,我們將其轉儲到cPickle(Python3下是_pickle)中並返回儲存在Pickle中的物件。稍後恢復模型是必要的,否則Python將無法直接從來自PostgreSQL的bytearray中恢復kmeans物件。

最後一行指定擴充套件語言:在這種情況下,我們使用Python 2,因此,副檔名稱為plpythonu。如果您想在Python 3中執行它,您應該使用名為plpython3u的擴充套件語言。

4. 儲存模型

建立模型但不用它做任何事情是沒有什麼意義的。所以,我們需要儲存它。為此,我們先建立一個模型表:

CREATE TABLE models (id SERIAL PRIMARY KEY,model BYTEA NOT NULL);

本例中,我們的表只有一個主鍵和一個位元組陣列欄位,即序列化的實際模型。請注意,它與我們定義的kmeans返回的資料型別相同。

一旦我們有了表格,我們就可以輕鬆地在模型中插入新記錄:

INSERT INTO models(model) SELECT kmeans('iris', array[]::text[], 3);

本例中,我們將columns引數作為空陣列傳遞,以使用表中的所有數值變數執行聚類。請考慮這只是一個例子。在生產案例中,您可能希望新增一些額外的欄位,以便更容易識別不同的模型。

5.顯示模型資訊

到目前為止,我們能夠建立一個模型並存儲它,但直接從資料庫中獲取它並不是很有用。你可以通過執行來檢查它

select * from models;

出於這個原因,我們需要回到Python以顯示有關我們模型的有用資訊。這是我們將要使用的函式:

CREATE OR replace FUNCTION get_kmeans_centroids(    model_table text, model_column text, model_id int)     RETURNS real[] AS$$from pandas import DataFramefrom cPickle import loads rv = plpy.execute('SELECT %s FROM %s WHERE id = %s;' %                   (plpy.quote_ident(model_column),                    plpy.quote_ident(model_table), model_id))model = loads(rv[0][model_column])ret=map(list,model.cluster_centers_)returnret$$ LANGUAGE plpythonu;

讓我們從頭開始:我們再次傳遞包含模型的表和包含二進位制的列。輸出由cPickle(Python 3下是_pickle)的載入函式讀取([here](https://www.postgresql.org/docs/10/static/plpython-database.html),您可以看到如何將plpython查詢的結果載入到Python中)。

載入模型後,我們知道所有kmeans物件都有一個屬性“cluster_centers_”,這是儲存質心的位置。質心是每組的平均向量,即每組中每個變數的平均值。即,它們儲存為numpy陣列,但由於plpython無法處理numpy陣列,我們需要將它們轉換為列表的列表。這就是為什麼返回的物件是列出每一行的輸出,產生列表的列表的原因,其中每個子列表代表一個組的質心。

這只是如何輸出模型的某個特徵的示例。您可以建立類似的函式來返回其他特徵,甚至是所有特徵。

我們來看看它的返回:

select get_kmeans_centroids('models','model',1);
get_kmeans_centroids
[[1.464, 0.244, 5.006, 3.418], [4.39355, 1.43387, 5.90161, 2.74839], [5.74211, 2.07105, 6.85, 3.07368]]

括號括起來的每個元素代表一個組,值是其平均值的向量。

6. 預測

現在我們有了一個模型,讓我們用它來做預測!在kmeans中,這意味著傳遞一組值(對應於每個變數)並獲取它所屬的組號。該函式與前一個函式非常相似:

CREATE OR replace FUNCTION predict_kmeans(model_tabletext,model_columntext,model_idint,input_valuesreal[])RETURNSint[]AS$$fromcPickleimportloadsrv = plpy.execute('SELECT %s FROM %s WHERE id = %s;' %                   (plpy.quote_ident(model_column)                  , plpy.quote_ident(model_table)                  , model_id))model = loads(rv[0][model_column])ret = model.predict(input_values)returnret$$ LANGUAGE plpythonu;

與前一個函式相比,我們新增一個輸入引數(input_values),傳遞一個表示案例(每個變數一個值)的輸入值,我們希望根據聚類獲取組值。

我們返回一個整數陣列,而不是返回一個浮點陣列,因為我們正在討論一個組索引。

select predict_kmeans('models','model',1,array[[0.5,0.5,0.5,0.5]]);#返回{1}

請注意,即使只傳遞一個元素,也需要傳遞一個數組的陣列。這與Python處理陣列的方式有關。

我們還可以將列名傳遞給函式,例如:

select species,predict_kmeans('models','model',1                ,array[[petal_length,petal_width,sepal_length,sepal_width]]) from iris;

如您所見,相關組與它們的種類密切相關。

結論

我們在本文中已經看到,您可以在不離開postgres的情況下訓練和使用機器學習。但是,您需要擁有Python的知識來準備一切。儘管如此,對於那些可能不知道如何用Python或任何其他語言進行操作的人來說,這可以是一個非常好的解決方案,可以在PostgreSQL中建立一個完整的機器學習工具包。

本文翻譯自MACHINE LEARNING IN POSTGRESQL PART 1: KMEANS CLUSTERING,https://www.cybertec-postgresql.com/en/machine-learning-in-postgresql-part-1-kmeans-clustering/

作者,Hernan Resnizky

P.S.

Pivot的Madlib(僅僅支援Linux和MacOS環境)外掛也可以讓PostgreSQL具有機器學習的功能,甚至有基於PostgreSQL來做推薦系統專用的資料庫(RecDB), 本文則是介紹一種通用、跨平臺的解決方案,是一種不錯的嘗試。

歡迎關注我的公眾號,alitrack

0de0c80ef76bacdaf83f64b62d6785f1.png

衡數提供下列服務,有意請留言

  • PySpark培訓

  • Excel培訓

  • 資料探勘諮詢

  • 資料探勘外包

  • 人才推薦