<jupyter_start><jupyter_text>Simple example of clustering with 2 attributes using SciKit Learn's k-Means and GMM (Gaussian Mixture Models) algorithms. Both models will be exported into ONNX format with the proper metadata.json required by OML Services for scoringCopyright (c) 2021 Oracle Corporation                              [The Universal Permissive License (UPL), Version 1.0](https://oss.oracle.com/licenses/upl/)---<jupyter_code>import sklearn
from sklearn import datasets
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

import skl2onnx
from skl2onnx import to_onnx

import onnxmltools
import json

from zipfile import ZipFile

# Loads the Breast Cancer dataset
bc=datasets.load_breast_cancer(as_frame=True)
# Creates a Pandas Dataframe
df = pd.DataFrame(bc.data, columns = bc.feature_names)

#Check the whole input dataset
df
# Let's plot two of the attributes to see the dispersion patterns

# Set a nicer looking chart style
plt.style.use('seaborn')

# Generate a Scatterplot of two attributes
plt.scatter(df['worst radius'], df['worst concavity'], cmap='plasma', edgecolor='k')
plt.xlabel("Worst Radius")
plt.ylabel("Worst Concavity")
plt.title("Original Data Scatter Plot")
# Let's create a subset with only the 2 attributes
df_sub = df[['worst radius','worst concavity']]
# Check the first 5 rows of the sub-selection
df_sub.head(5)<jupyter_output><empty_output><jupyter_text>k-Means clustering model Build Model---<jupyter_code># Define a k-Means clustering model with 2 clusters,
# and initialization by k-means++
from sklearn.cluster import KMeans
km_clus = sklearn.cluster.KMeans(init='k-means++', n_clusters=2)

# fit the model on the first 2 columns
km_clus.fit(df_sub)

# Return the predicted labels of the model
km_pred_labels=km_clus.predict(df_sub)

# Print the first 10 predicted labels
print(km_pred_labels[0:10])<jupyter_output>[0 0 0 1 0 1 0 1 1 1]<jupyter_text>Plot k-Means cluster predictions<jupyter_code># Let's plot the resulting k-Means predictions on the original scatterplot
fig_km, ax_km = plt.subplots(figsize=[10,7])
# Set a nicer looking default chart style
plt.style.use('seaborn')

# Generate the original Scatterplot of Worst Radius and Worst Concavity
# this time with colors per cluster by k-Means
scat = ax_km.scatter(df_sub['worst radius'], df_sub['worst concavity'], c=km_pred_labels, cmap='plasma', edgecolor='k')

# Plot the centroids as a Red X
centroids = km_clus.cluster_centers_
ax_km.scatter(centroids[:, 0], centroids[:, 1], 
            marker='x', s=200, linewidths=3,
            color='r', zorder=10)

# Create a Mesh Grid on the original plot dimensions for finding the 
# decision boundaries for each cluster (with a minor adjustment of 0.2)
x_min, x_max = df_sub.iloc[:, 0].min() - 2, df_sub.iloc[:, 0].max() + 2
y_min, y_max = df_sub.iloc[:, 1].min() - 0.2, df_sub.iloc[:, 1].max() + 0.2
WRadius_X, Wconcavity_Y = np.meshgrid(np.arange(x_min, x_max, 0.1), 
                                      np.arange(y_min, y_max, 0.1))
# Score k-Means cluster model across the mesh
final_grid_km = km_clus.predict(np.c_[WRadius_X.ravel(), Wconcavity_Y.ravel()])

# Draw a contour plot to illustrate the model cluster separation
final_grid_km = final_grid_km.reshape(WRadius_X.shape)
ax_km.contour(WRadius_X, Wconcavity_Y, final_grid_km)

ax_km.set_xlabel('Worst Radius', size=13)
ax_km.set_ylabel("Worst Concavity", size=13)
ax_km.set_title("Worst Radius vs Worst Concavity: 2 Clusters by k-Means\n"
                "k-Means centroids are marked with a red cross", size=18)

# Add a legend to the chart
legend1 = ax_km.legend(*scat.legend_elements(num=1),
                    loc="upper right", title="Cluster")
ax_km.add_artist(legend1)<jupyter_output><empty_output><jupyter_text>Export the k-Means model to ONNX formatWe will create and add the metadata.json file needed by OML Services to the Zip file<jupyter_code># Write the GMM model to ONNX format. Input data needs to be a numpy format
clus_onnx = to_onnx(km_clus, df_sub.to_numpy(), target_opset=12)
# Export the model to a file on disk
onnxmltools.utils.save_model(clus_onnx, './clus_onnx.onnx')
# Create the metadata.json file needed by Oracle Machine Learning Services
metadata = {"function":"clustering","clusteringDistanceOutput":"scores"}
with open('./metadata.json', mode='w') as f: 
       json.dump(metadata, f)
# Write the final ZIP File to be used in OML Services
with ZipFile('./clus_onnx.zip', mode='w') as zf:
    zf.write('./metadata.json')
    zf.write('./clus_onnx.onnx')<jupyter_output><empty_output><jupyter_text>Gaussian Mixture Model (GMM) clustering Build Model---<jupyter_code># Define a Gaussian Mixture Model with 2 clusters
from sklearn import cluster, datasets, mixture
gmm_clus = mixture.GaussianMixture(n_components=2, covariance_type="full", random_state=1)

# Fit the model on the first 2 columns
gmm_clus.fit(df_sub)

# Return the predicted probabilities of the model
gmm_clus_pred=gmm_clus.predict_proba(df_sub)

# Print the first 10 sets of predicted probabilities
# Probabilities of belonging to Cluster 0 and 1
gmm_probs_df = pd.DataFrame(gmm_clus.predict_proba(df_sub), 
                            columns={'Prob_of_Cluster0','Prob_of_Cluster1'})
gmm_probs_df.head(10).round(4)
# Return the predicted labels of the model
gmm_clus_labels=gmm_clus.predict(df_sub)

# Print the first 10 predicted labels
print(gmm_clus_labels[0:10])<jupyter_output>[0 0 0 0 0 0 0 1 0 0]<jupyter_text>Plot GMM cluster predictions<jupyter_code># Let's plot the resulting GMM predictions on the original scatterplot
# and also see the Elipsoids that represent the Gaussian distributions
fig_gmm, ax_gmm = plt.subplots(figsize=[10,7])

# Set a nicer looking default chart style
plt.style.use('seaborn')

# Generate the original Scatterplot of Worst Radius and Worst Concavity
# this time with colors per cluster by GMM
scat = ax_gmm.scatter(df_sub['worst radius'], df_sub['worst concavity'], 
                      c=gmm_clus_labels, cmap='plasma', edgecolor='k')
ax_gmm.set_xlabel('Worst Radius', size=13)
ax_gmm.set_ylabel("Worst Concavity", size=13)
ax_gmm.set_title("Worst Radius vs Worst Concavity: 2 Clusters by GMM\n"
                 "Including the Gaussian Ellipses", size=18)

# Plot the centroids as a Red X
gmm_means = gmm_clus.means_
ax_gmm.scatter(gmm_means[:, 0], gmm_means[:, 1], 
            marker='x', s=200, linewidths=3,
            color='r', zorder=10)

# Create a Mesh Grid on the original plot dimensions for finding the 
# decision boundaries for each GMM ellipses (with a minor adjustment of 0.2)
x_min, x_max = df_sub.iloc[:, 0].min() - 2, df_sub.iloc[:, 0].max() + 2
y_min, y_max = df_sub.iloc[:, 1].min() - 0.2, df_sub.iloc[:, 1].max() + 0.2
WRadius_X, Wconcavity_Y = np.meshgrid(np.arange(x_min, x_max, 0.1), 
                                      np.arange(y_min, y_max, 0.1))
Grid_Rad_Conc = np.array([WRadius_X.ravel(), Wconcavity_Y.ravel()]).T
# Score GMM cluster model across the mesh
Final_Grid = gmm_clus.score_samples(Grid_Rad_Conc)
# Reshape the mesh to conform with the shape of the original data
Final_Grid = Final_Grid.reshape(WRadius_X.shape)
# Plot the ellipsis
ax_gmm.contour(WRadius_X, Wconcavity_Y, Final_Grid)

# Add a legend to the chart
leg_gmm = ax_gmm.legend(*scat.legend_elements(num=1),
                        loc="upper right", title="Cluster")
ax_gmm.add_artist(leg_gmm)

# Check the weights, means and covariances
print('GMM weights:')
print(gmm_clus.weights_)
print('\nGMM Means:')
print(gmm_clus.means_)
print('\nGMM Covariances:')
print(gmm_clus.covariances_)<jupyter_output>GMM weights:
[0.38740444 0.61259556]

GMM Means:
[[20.45976511  0.46609291]
 [13.61907682  0.14956364]]

GMM Covariances:
[[[2.44852455e+01 1.51286739e-02]
  [1.51286739e-02 3.55704453e-02]]

 [[4.45314937e+00 9.46955958e-02]
  [9.46955958e-02 9.61637687e-03]]]<jupyter_text>Export the GMM model to ONNX formatWe will create and add the metadata.json file needed by OML Services to the Zip file<jupyter_code># Write the GMM model to ONNX format. Input data needs to be a numpy format
gmm_onnx = to_onnx(gmm_clus, df_sub.to_numpy(), target_opset=12)
# Export the model to a file on disk
onnxmltools.utils.save_model(gmm_onnx, './gmm_onnx.onnx')
# Create the metadata.json file needed by Oracle Machine Learning Services
# In this example we will return the Probabilities
metadata = {"function":"clustering","clusteringProbOutput":"probabilities"}
with open('./metadata.json', mode='w') as f: 
       json.dump(metadata, f)
# Write the final ZIP File to be used in OML Services
with ZipFile('./gmm_onnx.zip', mode='w') as zf:
    zf.write('./metadata.json')
    zf.write('./gmm_onnx.onnx')<jupyter_output><empty_output><jupyter_text>Extra useful verification for ONNX information<jupyter_code># Check the k-Means ONNX model
print(clus_onnx)
# Check the GMM ONNX model
print(gmm_onnx)<jupyter_output>ir_version: 7
producer_name: "skl2onnx"
producer_version: "1.10.3"
domain: "ai.onnx"
model_version: 0
doc_string: ""
graph {
  node {
    input: "X"
    input: "Ge_Gemmcst"
    input: "Ge_Gemmcst1"
    output: "Ge_Y0"
    name: "Ge_Gemm"
    op_type: "Gemm"
    attribute {
      name: "alpha"
      f: 1.0
      type: FLOAT
    }
    attribute {
      name: "beta"
      f: 1.0
      type: FLOAT
    }
    domain: ""
  }
  node {
    input: "X"
    input: "Ge_Gemmcst2"
    input: "Ge_Gemmcst3"
    output: "Ge_Y02"
    name: "Ge_Gemm1"
    op_type: "Gemm"
    attribute {
      name: "alpha"
      f: 1.0
      type: FLOAT
    }
    attribute {
      name: "beta"
      f: 1.0
      type: FLOAT
    }
    domain: ""
  }
  node {
    input: "Ge_Y0"
    output: "Re_reduced0"
    name: "Re_ReduceSumSquare"
    op_type: "ReduceSumSquare"
    attribute {
      name: "axes"
      ints: 1
      type: INTS
    }
    domain: ""
  }
  node {
    input: "Ge_Y02"
    output: "Re_reduced02"
    name: "Re_R[...]
{'fraction_non_alphanumeric': 0.11031344792719919, 'fraction_numerical': 0.031041456016177957, 'mean_word_length': 4.20578947368421, 'pattern_counts': {'":': 4, '<': 29, '<?xml version=': 0, '>': 29, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 3}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '651241', 'license': 'Apache-2.0', 'n_tokens_mistral': 3822, 'n_tokens_neox': 3542, 'n_words': 988, 'path': 'machine-learning/oml-services/SKLearn kMeans and GMM export to ONNX.ipynb', 'repo_name': 'edutidev/ORACLE-Associate', 'size': '9890'}