Ingénierie des données

ML UDF's in plateforme de données Actian, VectorH, and Vector - Part 2

Actian Corporation

6 août 2020

Machine Learning UDF montrant une main de robot, une main d'homme et un globe terrestre

Dans la première partie de cet article en deux parties, nous avons créé le modèle. Dans cette partie, nous allons créer les UDF dans la base de données.

Nous pouvons convertir le modèle en Python, et j'ai utilisé m2cgen pour transposer le modèle sklearn en modèle Python .

Je vais fabriquer 3 types d'UDF,

  1. Python UDF.
  2. JavaScript UDF.
  3. Enregistrement des données au format JSON, puis classification à l'aide des données JSON.

UDF Python

La ligne de code suivante nous donnera un modèle en Python.

import m2cgen as m2c
code = m2c.export_to_python(clf)
La sortie que nous obtenons est :
def score(input) :
return [0.2834483510261381 + input[0] * 0.4156346233598447
+ input[1] * 1.6410466066307934 + input[2]
* -2.4486206310542746 + input[3] * -1.0775840518519904,
1.271492823301712 + entrée[0] * 0.7334652955571552
+ input[1] * -2.0527321763924102 + input[2]
* 0.4049181379167901 + entrée[3] * -1.4276343377888174,
-1.403879236024429 + entrée[0] * -1.8886197150361799
+ input[1] * -1.701005052157171 + input[2]
* 2.803528886728411 + input[3] * 2.6749639949986195]
Comme m2cgen a besoin d'un tableau en entrée, nous donnons à l'entrée une chaîne de caractères et nous la divisons en valeurs flottantes.
input = [float(i) for i in lst.split(",")]

Mathématiques de la régression linéaire et de la régression logistique

La formule de régression linéaire est la suivante ;

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

La régression linéaire est davantage conçue pour prédire des valeurs numériques que pour résoudre un problème de classification.

Cependant, pour la régression logistique, nous aimerions obtenir un résultat entre 0 et 1. Pour cela, nous devons utiliser une fonction non linéaire appelée sigmoïde ;

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

Les résultats sont interprétés en termes de probabilités.

Nous avons 4 valeurs d'entrée et m2cgen nous donne facilement une équation linéaire avec nos entrées, le coefficient et les intercepts calculés par le modèle. Nous appliquons la fonction sigmoïde à l'équation ci-dessus et nous obtenons une classification un contre un.

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

Après avoir appliqué sigmod, nous obtenons un tableau. Comme notre UDF est scalaire, nous devons modifier le code pour renvoyer l'index du tableau qui a la probabilité maximale. Nous ajoutons simplement du code pour retourner l'index avec la valeur maximale ;

max_val=arr1[0]
for i in range(0,len(arr1)) :
si arr1[i] > max_val :
index=i
max_val=arr1[i]
return index+1
En combinant le tout, nous obtenons la fonction suivante ;
import 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))) + ((input[2]) * (2.1944766675309997))) + ((input[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)) :
si arr1[i] > max_val :
index=i
max_val=arr1[i]
return index+1
Notre structure UDF est prête, il ne nous reste plus qu'à ajouter CREATE OR REPLACE FUNCTION pour que la syntaxe soit correcte et qu'elle soit ajoutée à la base de données.
udf='''CREATE OR REPLACE FUNCTION Iris_classifier(lst VARCHAR(100) not null)
return (int not null)
EN LANGAGE 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))) + ((input[2]) * (2.1944766675309997))) + ((input[3]) * (2.0100453163309537))]
print(var0)
index=0
max_val=var0[0]
for i in range(0,len(var0)) :
si var0[i] > max_val :
index=i
max_val=var0[i]
return index+1
return score (lst)
'''

Notre UDF est prêt et il ne nous reste plus qu'à l'ajouter à la base de données.

cursor.execute(udf)
conn.commit()

L'UDF est ajouté à la base de données et peut être utilisé pour la classification des données. Remarquez que l'entrée est ajoutée sous la forme d'une chaîne, puisque m2cgen s'attend à ce qu'une chaîne soit introduite dans le modèle.

predict='''select CASE
WHEN species='Iris-setosa' THEN '1' WHEN species='Iris-versicolor' THEN '2'
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)
predict1.head()

JavaScript UDF

Pour transposer l'UDF JavaScript, il suffit de fournir les éléments suivants :

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))];
}

Ici, je renvoie l'indice de la valeur maximale et je n'utilise pas la fonction sigmoïde, car si je n'utilise pas la fonction sigmoïde, elle fonctionne sur les estimations du maximum de vraisemblance.

Il suffit de le modifier en fonction de la qualification UDF pour Javascript.

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()

Et notre UDF est ajouté à la base de données ; de même, nous pouvons l'utiliser pour la classification comme nous l'avons fait pour l'UDF Python .

UDF avec des données JSON

VectorH 6.0 et Vector 6.0 support également le type de données JSON. Nous pouvons donc convertir le modèle en données JSON, qui seront ensuite utilisées avec notre modèle.

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()

L'UDF peut être appelé simplement par la requête, comme indiqué dans Python UDF.

Le code détaillé est disponible à l'adresse suivante : https://github.com/ActianCorp/MachineLearningUDFs/blob/master/Vector-UDF.ipynb

Si vous avez des questions, n'hésitez pas à me contacter à l'adresse suivante : vidisha.sharma@actian.com

Conclusion

L'intérêt des UDF sur base de données pour l'évaluation ML réside dans la possibilité d'évaluer les données sur base de données à une vitesse fulgurante. Le modèle et les données se trouvent au même endroit, ce qui réduit les déplacements de données. Toutes les opérations étant exécutées sur la base de données, vos modèles d'apprentissage automatique fonctionneront extrêmement rapidement grâce au moteur Vector X100. Python est l'un des langages les plus utilisés pour le développement de l'apprentissage automatique, il sera donc très facile de transférer et de gérer les modèles Python et JavaScript sur la base de données Scalar FDU pour le scoring par lots et les cas d'utilisation de scoring en temps quasi-réel.

Pour en savoir plus sur les capacités de tous les produits Actian, visitez notre site Web.

logo avatar actian

À propos d'Actian Corporation

Actian facilite l'accès aux données. Notre plateforme de données simplifie la façon dont les gens connectent, gèrent et analysent les données dans les environnements cloud, hybrides et sur site . Avec des décennies d'expérience dans la gestion des données et l'analyse, Actian fournit des solutions de de haute performance qui permettent aux entreprises de prendre des décisions basées sur les données. Actian est reconnu par les principaux analystes et a reçu des prix de l'industrie pour sa performance et son innovation. Nos équipes partagent des cas d'utilisation éprouvés lors de conférences (par exemple, Strata Data) et contribuent à des projets à code source ouvert. Sur le blog d'Actian, nous abordons des sujets tels que l'ingestion de données en temps réel, l'analyse de données, la gouvernance données, la gestion des données, la qualité des données, l'intelligence des données et l'analyse pilotée par l'IA.