O KServe habilita inferência de modelos Machine Learning no Kubernetes e é totalmente integrado ao Kubeflow. A seguir vamos portar o modelo de classificação de categorias visto nos capítulos anteriores para o Kserve. Antes de começar os trabalhos com o modelo precisamos configurar as credenciais para que o Kserve consiga obter os artefatos no minio. Para usar o minio vamos criar uma secret com as credentiais necessárias e um service account para utilizarmos na subida do servico:
from kubernetes import client
from kserve import KServeClient
from kserve import constants
from kserve import utils
from kserve import V1beta1InferenceService
from kserve import V1beta1InferenceServiceSpec
from kserve import V1beta1PredictorSpec
from kserve import V1beta1SKLearnSpec
from minio import Minio
from minio.error import ResponseError
Agora vamos inicializar algumas variáveis de crendênciais do minio, paths para os modelos e namespace padrão:
Para armazenar o modelo, vamos criar um bucket no minio:
if not minioClient.bucket_exists(MINIO_MODEL_BUCKET):
minioClient.make_bucket(MINIO_MODEL_BUCKET)
Vamos efetuar o upload do arquivo de dados no minio para ser a entrada de dados para o trainamento do modelo, antes de executar o comando abaixo, faça o upload do arquivo para o seu notebook:
import pandas as pd
import nltk
from nltk.corpus import stopwords
nltk.download('stopwords')
obj = minioClient.get_object(
MINIO_MODEL_BUCKET,
MINIO_DATA_PRODUCT_PATH,
)
products_data = pd.read_csv(obj,delimiter=';', encoding='utf-8')
products_data.count()
products_data["informacao"] = products_data["nome"]+ products_data["descricao"]
# concatenando as colunas nome e descricao
products_data['informacao'] = products_data['nome'] + products_data['descricao']
# excluindo linhas com valor de informacao ou categoria NaN
products_data.dropna(subset=['informacao', 'categoria'], inplace=True)
products_data.drop(columns=['nome', 'descricao'], inplace=True)
stop_words=set(stopwords.words("portuguese"))
# transforma a string em caixa baixa e remove stopwords
products_data['sem_stopwords'] = products_data['informacao'].str.lower().apply(lambda x: ' '.join([word for word in x.split() if word not in (stop_words)]))
tokenizer = nltk.RegexpTokenizer(r"\w+")
products_data['tokens'] = products_data['sem_stopwords'].apply(tokenizer.tokenize) # aplica o regex tokenizer
products_data.drop(columns=['sem_stopwords','informacao'],inplace=True) # Exclui as colunas antigas
products_data["strings"]= products_data["tokens"].str.join(" ") # reunindo cada elemento da lista
products_data.head()
A segunda etapa é o treinamento do modelo:
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
X_train,X_test,y_train,y_test = train_test_split( # Separação dos dados para teste e treino
products_data["strings"],
products_data["categoria"],
test_size = 0.2,
random_state = 10
)
pipe = Pipeline([('vetorizador', CountVectorizer()), ("classificador", MultinomialNB())]) # novo
É possível testar a chamada do endpoint de inferência via notebook: Mas antes de testar o endpoint é necessário configurar o RBAC para acesso. Para fins de teste local iremos criar um RBAC super permissível, mas para ambientes produtivos precisamos refinar o RBAC: