ML UDF's in plateforme de données Actian, VectorH, and Vector - Part 2
Actian Corporation
6 août 2020

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,
- Python UDF.
- JavaScript UDF.
- 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.
S'abonner au blog d'Actian
Abonnez-vous au blogue d'Actian pour recevoir des renseignements sur les données directement à vous.
- Restez informé - Recevez les dernières informations sur l'analyse des données directement dans votre boîte de réception.
- Ne manquez jamais un article - Vous recevrez des mises à jour automatiques par courrier électronique pour vous avertir de la publication de nouveaux articles.
- Tout dépend de vous - Modifiez vos préférences de livraison en fonction de vos besoins.