Datentechnik

ML UDF's in Actian Data Platform, VectorH, und Vector - Teil 2

Actian Germany GmbH

6. August 2020

Maschinelles Lernen UDF zeigt eine Roboterhand, eine menschliche Hand und einen Globus

Im ersten Teil dieses zweiteiligen Artikels haben wir das Modell erstellt. In diesem Teil werden wir die UDFs in der Datenbank erstellen.

Wir können das Modell in Python konvertieren, und ich habe m2cgen verwendet, um das Sklearn-Modell in ein Python zu transpilieren

Ich werde 3 Arten von UDFs herstellen,

  1. Python UDF.
  2. JavaScript UDF.
  3. Speichern der Daten in JSON und anschließende Klassifizierung anhand der JSON-Daten.

Python UDF

Die folgende 1 Codezeile liefert uns ein Modell in Python.

m2cgen als m2c importieren
code = m2c.export_to_python(clf)
Die Ausgabe, die wir erhalten, ist :
def score(input):
return [0.2834483510261381 + input[0] * 0.4156346233598447
+ input[1] * 1.6410466066307934 + input[2]
* -2.4486206310542746 + input[3] * -1.0775840518519904,
1.271492823301712 + Eingang[0] * 0.7334652955571552
+ input[1] * -2.0527321763924102 + input[2]
* 0.4049181379167901 + input[3] * -1.4276343377888174,
-1.403879236024429 + input[0] * -1.8886197150361799
+ input[1] * -1.701005052157171 + input[2]
* 2.803528886728411 + input[3] * 2.6749639949986195]
Da m2cgen ein Array als Eingabe benötigt, geben wir input als String ein und zerlegen ihn in Float-Werte.
input = [float(i) for i in lst.split(",")]

Lineare Regression und logistische Regression - Mathematik

Die Formel für die lineare Regression lautet;

Y=Wo+ X1W1+ X2W2+ X3W3+ ......

Die lineare Regression ist eher für die Vorhersage numerischer Werte als für ein Klassifizierungsproblem gedacht.

Für die logistische Regression möchten wir jedoch eine Ausgabe zwischen 0 und 1, und dafür müssen wir eine nichtlineare Funktion namens Sigmoid verwenden, die so aussieht;

H(X) =1/(1 + e^ (-y))

Das Ergebnis wird in Form von Wahrscheinlichkeiten interpretiert.

Wir haben 4 Eingabewerte und m2cgen gibt uns einfach eine lineare Gleichung mit unseren Eingaben, Koeffizienten und Achsenabschnitten, die vom Modell berechnet wurden. Wir wenden die Sigmoid-Funktion auf die oben gezeigte Gleichung an und erhalten eine Einstufung im Vergleich zum Rest.

for i in range(0,len(var0)):
arr1.append( 1 / (1 + math.exp(-var0[i])))
print(arr1)

Nach Anwendung von sigmod erhalten wir ein Array. Da unsere UDF skalar ist, müssen wir den Code ändern, um den Index des Arrays zurückzugeben, der die größte Wahrscheinlichkeit hat. Wir fügen einfach Code hinzu, um den Index mit dem maximalen Wert zurückzugeben;

max_val=arr1[0]
for i in range(0,len(arr1)):
if arr1[i] > max_val:
index=i
max_val=arr1[i]
return index+1
Wenn man das alles zusammenfügt, sieht unsere Funktion wie folgt aus;
importiere math
def score (lst):
input = [float(i) for i in lst.split(",")]
var0= [((((0.24739569243110213) + ((input[0]) * (0.3677840447489154))) + ((input[1])) * (1.4151458935607388))) + ((input[2])) * (-2.124321635674482))) + ((input[3])) * (-0.9309638143559119)), ((((0.7060488675827682) + ((input[0]) * (0.6404296785789872))) + ((input[1])) * (-1.7889249557223028))) + ((input[2])) * (0.4056580513021318))) + ((input[3])) * (-1.106884750746711)), ((((-0.9529159159570318) + ((input[0]) * (-1.5615947756178696))) + ((input[1])) * (-1.1894433955845047))) + ((eingabe[2])) * (2.1944766675309997))) + ((eingabe[3])) * (2.0100453163309537))]
print(var0)
index=0
arr1=[]
for i in range(0,len(var0)):
arr1.append( 1 / (1 + math.exp(-var0[i])))
print(arr1)
max_val=arr1[0]
for i in range(0,len(arr1)):
if arr1[i] > max_val:
index=i
max_val=arr1[i]
return index+1
Unsere UDF-Struktur ist fertig, wir müssen nur noch CREATE OR REPLACE FUNCTION hinzufügen, damit die Syntax korrekt ist und der Datenbank hinzugefügt werden kann.
udf='''CREATE OR REPLACE FUNCTION Iris_classifier(lst VARCHAR(100) not null)
return (int nicht null)
ALS SPRACHE PYTHON

SOURCE=''
def score (lst):
input = [float(i) for i in lst.split(",")]
var0= [((((0.24739569243110213) + ((input[0]) * (0.3677840447489154))) + ((input[1])) * (1.4151458935607388))) + ((input[2])) * (-2.124321635674482))) + ((input[3])) * (-0.9309638143559119)), ((((0.7060488675827682) + ((input[0]) * (0.6404296785789872))) + ((input[1])) * (-1.7889249557223028))) + ((input[2])) * (0.4056580513021318))) + ((input[3])) * (-1.106884750746711)), ((((-0.9529159159570318) + ((input[0]) * (-1.5615947756178696))) + ((input[1])) * (-1.1894433955845047))) + ((eingabe[2])) * (2.1944766675309997))) + ((eingabe[3])) * (2.0100453163309537))]
print(var0)
index=0
max_val=var0[0]
for i in range(0,len(var0)):
if var0[i] > max_val:
index=i
max_val=var0[i]
return index+1
return score (lst)'
'''

Unsere UDF ist fertig, wir müssen sie nur noch der Datenbank hinzufügen.

cursor.execute(udf)
conn.commit()

Die UDF wird der Datenbank hinzugefügt und kann für die Klassifizierung der Daten verwendet werden. Beachten Sie, dass die Eingabe als String hinzugefügt wird, da m2cgen einen String als Eingabe für das Modell erwartet.

predict='''select CASE
WHEN species='Iris-setosa' THEN '1'
WHEN species='Iris-versicolor' THEN '2'
ELSE '3'
END as species, Iris_classifier (sepallengthcm || ',' || sepalwidthcm || ',' || petallengthcm || ',' || petalwidthcm ) as classify from iris'''
predict1=pd.read_sql(predict, conn)
vorhersage1.head()

JavaScript UDF

Für die Umsetzung der JavaScript-UDF müssen wir nur Folgendes bereitstellen:

code = m2c.export_to_javascript(clf)
output generated is
function score(input) {
return [((((0.2901789521827987) + ((input[0]) * (0.4467535618836661))) + ((input[1]) * (1.5843519667681565))) + ((input[2]) * (-2.409947591791464))) + ((input[3]) * (-1.0736156286007468)), ((((0.8330817501826279) + ((input[0]) * (1.0259003852575856))) + ((input[1]) * (-2.4327046722797347))) + ((input[2]) * (0.48745117088772905))) + ((input[3]) * (-1.8329094419137872)), ((((-1.141764377255606) + ((input[0]) * (-2.35933886039274))) + ((input[1]) * (-1.2090666108474617))) + ((input[2]) * (2.981435002839768))) + ((input[3]) * (2.99871035615134))];
}

Hier gebe ich den Index für den Maximalwert zurück und verwende nicht die Sigmoid-Funktion, denn wenn ich die Sigmoid-Funktion nicht verwende, arbeitet sie mit den Maximum-Likelihood-Schätzungen.

Wir müssen sie nur gemäß der UDF-Qualifikation für Javascript ändern.

udf_JS ='''create function  iris_lr_javascript1(lst VARCHAR(100) not
null) return (int not null) AS LANGUAGE JAVASCRIPT SOURCE='
function score(lst) {
var input = lst.split(",").map(function(item) {  return
parseFloat(item); });
nums=[((((0.2901789521827987) + ((input[0]) * (0.4467535618836661))) + ((input[1]) * (1.5843519667681565))) + ((input[2]) * (-2.409947591791464))) + ((input[3]) * (-1.0736156286007468)), ((((0.8330817501826279) + ((input[0]) * (1.0259003852575856))) + ((input[1]) * (-2.4327046722797347))) + ((input[2]) * (0.48745117088772905))) + ((input[3]) * (-1.8329094419137872)), ((((-1.141764377255606) + ((input[0]) * (-2.35933886039274))) + ((input[1]) * (-1.2090666108474617))) + ((input[2]) * (2.981435002839768))) + ((input[3]) * (2.99871035615134))];
var index = 0;
for (var i = 0; i < nums.length; i++) {
index = nums[i] > nums[index] ? i : index;
}
return index+1;
}
return score(lst)'
'''
cursor.execute(udf_JS)
conn.commit()

Und unsere UDF wird in die Datenbank eingefügt; ebenso können wir sie für die Klassifizierung verwenden, wie wir es bei der Python getan haben.

UDF mit JSON-Daten

VectorH 6.0 und Vector 6.0 unterstützen auch den JSON-Datentyp. So können wir das Modell in JSON-Daten konvertieren, die später mit unserem Modell verwendet werden können.

import json
model_param = {}
model_param['coef'] = clf.coef_.tolist()
model_param['intercept'] =clf.intercept_.tolist()
b = json.dumps(model_param)
print(b)
{"coef": [[0.4467535618836661, 1.5843519667681565, -2.409947591791464, -1.0736156286007468], [1.0259003852575856, -2.4327046722797347, 0.48745117088772905, -1.8329094419137872], [-2.35933886039274, -1.2090666108474617, 2.981435002839768, 2.99871035615134]], "intercept": [0.2901789521827987, 0.8330817501826279, -1.141764377255606]}
jsonstr='''create function  iris_lr_json(lst VARCHAR(100) not null)
return (int not null) AS LANGUAGE python SOURCE='
import json
def score1 (lst):
input = [float(i) for i in lst.split(",")]
json_data = "{"coef": [[0.4156346233598447, 1.6410466066307934, 
-2.4486206310542746, -1.0775840518519904], [0.7334652955571552, 
-2.0527321763924102, 0.4049181379167901, -1.4276343377888174], 
[-1.8886197150361799, -1.701005052157171, 2.803528886728411, 
2.6749639949986195]], "intercept": [0.2834483510261381, 
1.271492823301712, -1.403879236024429]}"
dictjson = json.loads(json_data)
# raise Exception("it is %s" % str(dictjson))
var0=[dictjson["intercept"][0]+ input[0]*dictjson["coef"][0][0] +
input[1]*dictjson["coef"][0][1]+input[2]*dictjson["coef"][0][2] +
input[3]*dictjson["coef"][0][3], dictjson["intercept"][1]+
input[0]*dictjson["coef"][1][0] +input[1]*dictjson["coef"][1][1]+
input[2]*dictjson["coef"][1][2] + input[3]*dictjson["coef"][1][3],
dictjson["intercept"][2]+ input[0]*dictjson["coef"][2][0] +
input[1]*dictjson["coef"][2][1]+input[2]*dictjson["coef"][2][2] +
input[3]*dictjson["coef"][2][3]]
#print(var0)
index=0
max_val=var0[0]
for i in range(0,len(var0)):
if var0[i] > max_val:
index=i
max_val=var0[i]
return index+1
return score (lst)'
'''
cursor.execute(jsonstr)
conn.commit()

UDF kann einfach durch die Anfrage aufgerufen werden, wie in Python UDF gezeigt.

Den ausführlichen Code finden Sie unter https://github.com/ActianCorp/MachineLearningUDFs/blob/master/Vector-UDF.ipynb.

Falls Sie Fragen haben, können Sie mich gerne unter vidisha.sharma@actian.com erreichen.

Schlussfolgerung

Die Attraktivität von datenbankinternen UDFs für ML-Scoring liegt in der Möglichkeit, Daten in der Datenbank mit halsbrecherischer Geschwindigkeit zu bewerten. Das Modell und die Daten befinden sich am selben Ort, was die Datenbewegungen reduziert. Da alle Operationen in der Datenbank ausgeführt werden, laufen Ihre Modelle des Maschinelles Lernen mit der Vector X100-Engine extrem schnell. Python ist eine der am häufigsten verwendeten Sprachen für die ML-Entwicklung, so dass es sehr einfach sein wird,Python und JavaScript-Modelle auf Scalar Nutzer Defined Functions (UDFs) für Batch-Scoring und Near-Real-Time-Scoring-Anwendungsfälle zu übertragen und zu verwalten .

Um mehr über die Möglichkeiten aller ActianProdukte zu erfahren, besuchen Sie unsere Website.

actian avatar logo

Über Actian Corporation

Actian macht Daten einfach. Unsere Datenplattform vereinfacht die Verbindung, Verwaltung und Analyse von Daten in Cloud-, Hybrid- und lokalen Umgebungen. Mit jahrzehntelanger Erfahrung in den Bereichen Datenmanagement und -analyse liefert Actian leistungsstarke Lösungen, die es Unternehmen ermöglichen, datengesteuerte Entscheidungen zu treffen. Actian wird von führenden Analysten anerkannt und wurde für seine Leistung und Innovation mit Branchenpreisen ausgezeichnet. Unsere Teams präsentieren bewährte Anwendungsfälle auf Konferenzen (z. B. Strata Data) und tragen zu Open-Source-Projekten bei. Im ActianBlog behandeln wir Themen wie Echtzeit-Dateneingabe, Datenanalyse, Data Governance, Datenmanagement, Datenqualität, Datenintelligenz und KI-gesteuerte Analysen.