ML UDF's en Actian Data Platform, VectorH, y Vector - Parte 2
Corporación Actian
6 de agosto de 2020

En la primera parte de este artículo de dos partes, creamos el modelo. En esta entrega, crearemos las UDF en base de datos.
Podemos convertir el modelo a Python, y utilicé m2cgen para transpilar el modelo sklearn a modelo Python
Haré 3 tipos de UDF,
- UDF de Python.
- JavaScript UDF.
- Almacenamiento de los datos en JSON y, a continuación, clasificación mediante datos JSON.
Python UDF
Siguiendo 1 línea de código obtendremos un modelo en Python.
importar m2cgen como m2c code = m2c.export_to_python(clf) La salida que obtenemos es : def puntuación(entrada): return [0.2834483510261381 + input[0] * 0.4156346233598447 + entrada[1] * 1.6410466066307934 + entrada[2] -2.4486206310542746 + entrada[3] * -1.0775840518519904, 1.271492823301712 + entrada[0] * 0.7334652955571552 + entrada[1] * -2.0527321763924102 + entrada[2] * 0.4049181379167901 + entrada[3] * -1.4276343377888174, -1.403879236024429 + entrada[0] * -1.8886197150361799 + entrada[1] * -1.701005052157171 + entrada[2] * 2.803528886728411 + entrada[3] * 2.6749639949986195] Como m2cgen necesita un array como entrada le damos input como cadena y la dividimos en valores float. input = [float(i) for i in lst.split(",")]
Matemáticas de regresión lineal y regresión logística
La fórmula de la regresión lineal es
Y=Wo+ X1W1+ X2W2+ X3W3+ ......
La regresión lineal está diseñada más para predecir valores numéricos que para un problema de clasificación.
Sin embargo, para la regresión logística, nos gustaría una salida entre 0 y 1, para ello, tenemos que utilizar una función no lineal llamada sigmoide que es;
H(X) =1/(1 + e^ (-y))
El resultado se interpreta en términos de probabilidades.
Tenemos 4 valores de entrada y m2cgen nos da fácilmente una ecuación lineal con nuestras entradas , coeficiente e interceptos calculados por el modelo. Aplicamos la función sigmoidea en la ecuación que se muestra arriba y nos da una clasificación frente al resto.
for i in range(0,len(var0)): arr1.append( 1 / (1 + math.exp(-var0[i]))) print(arr1)
Después de aplicar sigmod, obtenemos un array. Como nuestro UDF es escalar, necesitamos modificar el código para devolver el índice del array, que tiene la máxima probabilidad. Sólo tenemos que añadir código para devolver el índice con el valor máximo;
max_val=arr1[0] for i in range(0,len(arr1)): if arr1[i] > max_val: index=i max_val=arr1[i] return índice+1 juntando todo hace nuestra función como; import math def puntuación (lst): input = [float(i) for i in lst.split(",")] var0= [((((0.24739569243110213) + ((input[0]) * (0.3677840447489154))) + ((entrada[1]) * (1.4151458935607388))) + ((entrada[2]) * (-2.124321635674482))) + ((entrada[3]) * (-0.9309638143559119)), ((((0.7060488675827682) + ((entrada[0]) * (0.6404296785789872))) + ((entrada[1]) * (-1.7889249557223028))) + ((entrada[2]) * (0.4056580513021318))) + ((entrada[3]) * (-1.106884750746711)), ((((-0.9529159159570318) + ((entrada[0]) * (-1.5615947756178696))) + ((entrada[1]) * (-1.1894433955845047))) + ((entrada[2]) * (2.1944766675309997))) + ((entrada[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 Nuestra estructura UDF está lista, sólo necesitamos añadir CREATE OR REPLACE FUNCTION para que la sintaxis sea correcta y se añada a la base de datos. udf='''CREATE OR REPLACE FUNCTION Iris_classifier(lst VARCHAR(100) not null) return (int not null) COMO LENGUAJE PYTHON SOURCE=' def puntuación (lst): input = [float(i) for i in lst.split(",")] var0= [((((0.24739569243110213) + ((input[0]) * (0.3677840447489154)) + ((entrada[1]) * (1.4151458935607388))) + ((entrada[2]) * (-2.124321635674482))) + ((entrada[3]) * (-0.9309638143559119)), ((((0.7060488675827682) + ((entrada[0]) * (0.6404296785789872))) + ((entrada[1]) * (-1.7889249557223028))) + ((entrada[2]) * (0.4056580513021318))) + ((entrada[3]) * (-1.106884750746711)), ((((-0.9529159159570318) + ((entrada[0]) * (-1.5615947756178696))) + ((entrada[1]) * (-1.1894433955845047))) + ((entrada[2]) * (2.1944766675309997))) + ((entrada[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 índice+1 return puntuación (lst)' '''
Nuestra UDF está lista, y sólo tenemos que añadirla a la base de datos.
cursor.execute(udf) conn.commit()
La UDF se añade a la base de datos y se puede utilizar para la clasificación de los datos, observe que la entrada se añade como una cadena, ya que m2cgen espera una cadena como entrada al modelo.
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) predict1.head()
JavaScript UDF
Para transpilar la UDF de JavaScript, sólo tenemos que proporcionar lo siguiente:
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))]; }
Aquí, estoy devolviendo el índice para el valor máximo y no utilizar la función sigmoidea como si no utilizar sigmoidea funciona en las estimaciones de máxima verosimilitud.
Sólo tenemos que cambiarlo según la calificación UDF para 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()
Y nuestra UDF se añade a la base de datos; asimismo, podemos utilizarla para la clasificación como hicimos con la UDF de Python.
UDF con datos JSON
VectorH 6.0 y Vector 6.0 también soportan el tipo de datos JSON. Así que podemos convertir el modelo en datos JSON, más tarde para ser utilizado con nuestro modelo.
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 puede ser llamado simplemente por la consulta, como se muestra en Python UDF.
Encontrará el código detallado en https://github.com/ActianCorp/MachineLearningUDFs/blob/master/Vector-UDF.ipynb
Si tiene alguna pregunta, no dude en ponerse en contacto conmigo en vidisha.sharma@actian.com.
Conclusión
El atractivo de las UDF en la base de datos para la calificación ML es la capacidad de calificar datos en la base de datos a una velocidad vertiginosa. El modelo y los datos están en el mismo lugar, lo que reduce el movimiento de datos. Con todas las operaciones ejecutándose en la base de datos, sus modelos de aprendizaje automático se ejecutarán extremadamente rápido utilizando el motor Vector X100. Python es uno de los lenguajes más utilizados para el desarrollo de ML, por lo que será muy fácil la transición y la gestión de modelos Python y JavaScript en la base de datos Scalar UDFs para la puntuación por lotes y casos de uso de puntuación casi en tiempo real.
Para obtener más información sobre las capacidades de todos los productos Actian, visite nuestro sitio web.
Suscríbase al blog de Actian
Suscríbase al blog de Actian para recibir información sobre datos directamente en su correo electrónico.
- Manténgase informado: reciba lo último en análisis de datos directamente en su bandeja de entrada.
- No se pierda ni una publicación: recibirá actualizaciones automáticas por correo electrónico que le avisarán cuando se publiquen nuevas publicaciones.
- Todo depende de usted: cambie sus preferencias de entrega para adaptarlas a sus necesidades.