Files
Man1130/jupyter/Man1130-python-comission/course_materials/Note/CH8C_SVC-scratch.ipynb
louiscklaw e44aead3d5 update,
2025-02-01 01:58:19 +08:00

858 lines
74 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Support Vector Machines"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## IRIS data set\n",
"> - **label**: species \n",
"> - **features**: sepal_length, sepal_width, petal_length, petal_width"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>sepal_length</th>\n",
" <th>sepal_width</th>\n",
" <th>petal_length</th>\n",
" <th>petal_width</th>\n",
" <th>species</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>5.1</td>\n",
" <td>3.5</td>\n",
" <td>1.4</td>\n",
" <td>0.2</td>\n",
" <td>setosa</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>4.9</td>\n",
" <td>3.0</td>\n",
" <td>1.4</td>\n",
" <td>0.2</td>\n",
" <td>setosa</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>4.7</td>\n",
" <td>3.2</td>\n",
" <td>1.3</td>\n",
" <td>0.2</td>\n",
" <td>setosa</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>4.6</td>\n",
" <td>3.1</td>\n",
" <td>1.5</td>\n",
" <td>0.2</td>\n",
" <td>setosa</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>5.0</td>\n",
" <td>3.6</td>\n",
" <td>1.4</td>\n",
" <td>0.2</td>\n",
" <td>setosa</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" sepal_length sepal_width petal_length petal_width species\n",
"0 5.1 3.5 1.4 0.2 setosa\n",
"1 4.9 3.0 1.4 0.2 setosa\n",
"2 4.7 3.2 1.3 0.2 setosa\n",
"3 4.6 3.1 1.5 0.2 setosa\n",
"4 5.0 3.6 1.4 0.2 setosa"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import seaborn as sns\n",
"iris = sns.load_dataset('iris')\n",
"iris.head()"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>sepal_length</th>\n",
" <th>sepal_width</th>\n",
" <th>petal_length</th>\n",
" <th>petal_width</th>\n",
" <th>species</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>5.1</td>\n",
" <td>3.5</td>\n",
" <td>1.4</td>\n",
" <td>0.2</td>\n",
" <td>setosa</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>4.9</td>\n",
" <td>3.0</td>\n",
" <td>1.4</td>\n",
" <td>0.2</td>\n",
" <td>setosa</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>4.7</td>\n",
" <td>3.2</td>\n",
" <td>1.3</td>\n",
" <td>0.2</td>\n",
" <td>setosa</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>4.6</td>\n",
" <td>3.1</td>\n",
" <td>1.5</td>\n",
" <td>0.2</td>\n",
" <td>setosa</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>5.0</td>\n",
" <td>3.6</td>\n",
" <td>1.4</td>\n",
" <td>0.2</td>\n",
" <td>setosa</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" sepal_length sepal_width petal_length petal_width species\n",
"0 5.1 3.5 1.4 0.2 setosa\n",
"1 4.9 3.0 1.4 0.2 setosa\n",
"2 4.7 3.2 1.3 0.2 setosa\n",
"3 4.6 3.1 1.5 0.2 setosa\n",
"4 5.0 3.6 1.4 0.2 setosa"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Make it binary\n",
"data=iris[iris['species']!='virginica']\n",
"data.head()"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(100, 3)\n",
"(100,)\n"
]
}
],
"source": [
"X = data[['sepal_width','petal_width','sepal_length']]\n",
"y = data['species']\n",
"print(X.shape)\n",
"print(y.shape)"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"scrolled": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(75, 3)\n",
"(25, 3)\n"
]
}
],
"source": [
"from sklearn.model_selection import train_test_split\n",
"Xtrain, Xtest, ytrain, ytest = train_test_split(X, y, random_state=2)\n",
"print(Xtrain.shape)\n",
"print(Xtest.shape)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Estimation"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<style>#sk-container-id-2 {color: black;background-color: white;}#sk-container-id-2 pre{padding: 0;}#sk-container-id-2 div.sk-toggleable {background-color: white;}#sk-container-id-2 label.sk-toggleable__label {cursor: pointer;display: block;width: 100%;margin-bottom: 0;padding: 0.3em;box-sizing: border-box;text-align: center;}#sk-container-id-2 label.sk-toggleable__label-arrow:before {content: \"▸\";float: left;margin-right: 0.25em;color: #696969;}#sk-container-id-2 label.sk-toggleable__label-arrow:hover:before {color: black;}#sk-container-id-2 div.sk-estimator:hover label.sk-toggleable__label-arrow:before {color: black;}#sk-container-id-2 div.sk-toggleable__content {max-height: 0;max-width: 0;overflow: hidden;text-align: left;background-color: #f0f8ff;}#sk-container-id-2 div.sk-toggleable__content pre {margin: 0.2em;color: black;border-radius: 0.25em;background-color: #f0f8ff;}#sk-container-id-2 input.sk-toggleable__control:checked~div.sk-toggleable__content {max-height: 200px;max-width: 100%;overflow: auto;}#sk-container-id-2 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {content: \"▾\";}#sk-container-id-2 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-2 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-2 input.sk-hidden--visually {border: 0;clip: rect(1px 1px 1px 1px);clip: rect(1px, 1px, 1px, 1px);height: 1px;margin: -1px;overflow: hidden;padding: 0;position: absolute;width: 1px;}#sk-container-id-2 div.sk-estimator {font-family: monospace;background-color: #f0f8ff;border: 1px dotted black;border-radius: 0.25em;box-sizing: border-box;margin-bottom: 0.5em;}#sk-container-id-2 div.sk-estimator:hover {background-color: #d4ebff;}#sk-container-id-2 div.sk-parallel-item::after {content: \"\";width: 100%;border-bottom: 1px solid gray;flex-grow: 1;}#sk-container-id-2 div.sk-label:hover label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-2 div.sk-serial::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: 0;}#sk-container-id-2 div.sk-serial {display: flex;flex-direction: column;align-items: center;background-color: white;padding-right: 0.2em;padding-left: 0.2em;position: relative;}#sk-container-id-2 div.sk-item {position: relative;z-index: 1;}#sk-container-id-2 div.sk-parallel {display: flex;align-items: stretch;justify-content: center;background-color: white;position: relative;}#sk-container-id-2 div.sk-item::before, #sk-container-id-2 div.sk-parallel-item::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: -1;}#sk-container-id-2 div.sk-parallel-item {display: flex;flex-direction: column;z-index: 1;position: relative;background-color: white;}#sk-container-id-2 div.sk-parallel-item:first-child::after {align-self: flex-end;width: 50%;}#sk-container-id-2 div.sk-parallel-item:last-child::after {align-self: flex-start;width: 50%;}#sk-container-id-2 div.sk-parallel-item:only-child::after {width: 0;}#sk-container-id-2 div.sk-dashed-wrapped {border: 1px dashed gray;margin: 0 0.4em 0.5em 0.4em;box-sizing: border-box;padding-bottom: 0.4em;background-color: white;}#sk-container-id-2 div.sk-label label {font-family: monospace;font-weight: bold;display: inline-block;line-height: 1.2em;}#sk-container-id-2 div.sk-label-container {text-align: center;}#sk-container-id-2 div.sk-container {/* jupyter's `normalize.less` sets `[hidden] { display: none; }` but bootstrap.min.css set `[hidden] { display: none !important; }` so we also need the `!important` here to be able to override the default hidden behavior on the sphinx rendered scikit-learn.org. See: https://github.com/scikit-learn/scikit-learn/issues/21755 */display: inline-block !important;position: relative;}#sk-container-id-2 div.sk-text-repr-fallback {display: none;}</style><div id=\"sk-container-id-2\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>SVC(C=10, kernel=&#x27;linear&#x27;)</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item\"><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-2\" type=\"checkbox\" checked><label for=\"sk-estimator-id-2\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">SVC</label><div class=\"sk-toggleable__content\"><pre>SVC(C=10, kernel=&#x27;linear&#x27;)</pre></div></div></div></div></div>"
],
"text/plain": [
"SVC(C=10, kernel='linear')"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from sklearn.svm import SVC\n",
"\n",
"svc1 = SVC(kernel='linear',C=10)\n",
"svc1.fit(Xtrain,ytrain)"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array(['versicolor', 'setosa', 'versicolor', 'setosa', 'setosa', 'setosa',\n",
" 'setosa', 'setosa', 'setosa', 'setosa'], dtype=object)"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ypred = svc1.predict(Xtest)\n",
"ypred[:10]"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[2.3, 0.3, 4.5],\n",
" [3.4, 0.4, 5.4],\n",
" [3.5, 0.6, 5. ],\n",
" [2.4, 1. , 4.9]])"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"svc1.support_vectors_"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[16, 0],\n",
" [ 0, 9]])"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from sklearn.metrics import confusion_matrix\n",
"confusion_matrix(ytest,ypred)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Data Visualization"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"text/plain": [
"array([0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0,\n",
" 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n",
" 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0,\n",
" 0, 0, 1, 1, 0, 0, 1, 0, 0])"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from sklearn.preprocessing import LabelEncoder\n",
"y1 = LabelEncoder().fit_transform(ytrain)\n",
"y1"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": true
},
"outputs": [
{
"data": {
"text/plain": [
"array([2. , 2.03030303, 2.06060606, 2.09090909, 2.12121212,\n",
" 2.15151515, 2.18181818, 2.21212121, 2.24242424, 2.27272727,\n",
" 2.3030303 , 2.33333333, 2.36363636, 2.39393939, 2.42424242,\n",
" 2.45454545, 2.48484848, 2.51515152, 2.54545455, 2.57575758,\n",
" 2.60606061, 2.63636364, 2.66666667, 2.6969697 , 2.72727273,\n",
" 2.75757576, 2.78787879, 2.81818182, 2.84848485, 2.87878788,\n",
" 2.90909091, 2.93939394, 2.96969697, 3. , 3.03030303,\n",
" 3.06060606, 3.09090909, 3.12121212, 3.15151515, 3.18181818,\n",
" 3.21212121, 3.24242424, 3.27272727, 3.3030303 , 3.33333333,\n",
" 3.36363636, 3.39393939, 3.42424242, 3.45454545, 3.48484848,\n",
" 3.51515152, 3.54545455, 3.57575758, 3.60606061, 3.63636364,\n",
" 3.66666667, 3.6969697 , 3.72727273, 3.75757576, 3.78787879,\n",
" 3.81818182, 3.84848485, 3.87878788, 3.90909091, 3.93939394,\n",
" 3.96969697, 4. , 4.03030303, 4.06060606, 4.09090909,\n",
" 4.12121212, 4.15151515, 4.18181818, 4.21212121, 4.24242424,\n",
" 4.27272727, 4.3030303 , 4.33333333, 4.36363636, 4.39393939,\n",
" 4.42424242, 4.45454545, 4.48484848, 4.51515152, 4.54545455,\n",
" 4.57575758, 4.60606061, 4.63636364, 4.66666667, 4.6969697 ,\n",
" 4.72727273, 4.75757576, 4.78787879, 4.81818182, 4.84848485,\n",
" 4.87878788, 4.90909091, 4.93939394, 4.96969697, 5. ])"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import numpy as np\n",
"xx = np.linspace(2, 5, 100) #(100,)\n",
"xx"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.11/site-packages/sklearn/base.py:450: UserWarning: X does not have valid feature names, but SVC was fitted with feature names\n",
" warnings.warn(\n"
]
},
{
"ename": "ValueError",
"evalue": "X has 2 features, but SVC is expecting 3 features as input.",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[0;32mIn [10], line 9\u001b[0m\n\u001b[1;32m 6\u001b[0m YY, XX \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39mmeshgrid(yy, xx) \u001b[38;5;66;03m#(100,100) and (100,100) Replicate the data\u001b[39;00m\n\u001b[1;32m 8\u001b[0m xy \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39mvstack([XX\u001b[38;5;241m.\u001b[39mravel(), YY\u001b[38;5;241m.\u001b[39mravel()])\u001b[38;5;241m.\u001b[39mT \u001b[38;5;66;03m# (10000,2)\u001b[39;00m\n\u001b[0;32m----> 9\u001b[0m Z \u001b[38;5;241m=\u001b[39m \u001b[43msvc1\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdecision_function\u001b[49m\u001b[43m(\u001b[49m\u001b[43mxy\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241m.\u001b[39mreshape(XX\u001b[38;5;241m.\u001b[39mshape) \u001b[38;5;66;03m#(100,100)\u001b[39;00m\n",
"File \u001b[0;32m~/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.11/site-packages/sklearn/svm/_base.py:775\u001b[0m, in \u001b[0;36mBaseSVC.decision_function\u001b[0;34m(self, X)\u001b[0m\n\u001b[1;32m 748\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mdecision_function\u001b[39m(\u001b[38;5;28mself\u001b[39m, X):\n\u001b[1;32m 749\u001b[0m \u001b[38;5;124;03m\"\"\"Evaluate the decision function for the samples in X.\u001b[39;00m\n\u001b[1;32m 750\u001b[0m \n\u001b[1;32m 751\u001b[0m \u001b[38;5;124;03m Parameters\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 773\u001b[0m \u001b[38;5;124;03m transformation of ovo decision function.\u001b[39;00m\n\u001b[1;32m 774\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m--> 775\u001b[0m dec \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_decision_function\u001b[49m\u001b[43m(\u001b[49m\u001b[43mX\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 776\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdecision_function_shape \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124movr\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mclasses_) \u001b[38;5;241m>\u001b[39m \u001b[38;5;241m2\u001b[39m:\n\u001b[1;32m 777\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m _ovr_decision_function(dec \u001b[38;5;241m<\u001b[39m \u001b[38;5;241m0\u001b[39m, \u001b[38;5;241m-\u001b[39mdec, \u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mclasses_))\n",
"File \u001b[0;32m~/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.11/site-packages/sklearn/svm/_base.py:533\u001b[0m, in \u001b[0;36mBaseLibSVM._decision_function\u001b[0;34m(self, X)\u001b[0m\n\u001b[1;32m 519\u001b[0m \u001b[38;5;124;03m\"\"\"Evaluates the decision function for the samples in X.\u001b[39;00m\n\u001b[1;32m 520\u001b[0m \n\u001b[1;32m 521\u001b[0m \u001b[38;5;124;03mParameters\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 529\u001b[0m \u001b[38;5;124;03m in the model.\u001b[39;00m\n\u001b[1;32m 530\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 531\u001b[0m \u001b[38;5;66;03m# NOTE: _validate_for_predict contains check for is_fitted\u001b[39;00m\n\u001b[1;32m 532\u001b[0m \u001b[38;5;66;03m# hence must be placed before any other attributes are used.\u001b[39;00m\n\u001b[0;32m--> 533\u001b[0m X \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_validate_for_predict\u001b[49m\u001b[43m(\u001b[49m\u001b[43mX\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 534\u001b[0m X \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_compute_kernel(X)\n\u001b[1;32m 536\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_sparse:\n",
"File \u001b[0;32m~/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.11/site-packages/sklearn/svm/_base.py:611\u001b[0m, in \u001b[0;36mBaseLibSVM._validate_for_predict\u001b[0;34m(self, X)\u001b[0m\n\u001b[1;32m 608\u001b[0m check_is_fitted(\u001b[38;5;28mself\u001b[39m)\n\u001b[1;32m 610\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m callable(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mkernel):\n\u001b[0;32m--> 611\u001b[0m X \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_validate_data\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 612\u001b[0m \u001b[43m \u001b[49m\u001b[43mX\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 613\u001b[0m \u001b[43m \u001b[49m\u001b[43maccept_sparse\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mcsr\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 614\u001b[0m \u001b[43m \u001b[49m\u001b[43mdtype\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mnp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfloat64\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 615\u001b[0m \u001b[43m \u001b[49m\u001b[43morder\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mC\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 616\u001b[0m \u001b[43m \u001b[49m\u001b[43maccept_large_sparse\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 617\u001b[0m \u001b[43m \u001b[49m\u001b[43mreset\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 618\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 620\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_sparse \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m sp\u001b[38;5;241m.\u001b[39misspmatrix(X):\n\u001b[1;32m 621\u001b[0m X \u001b[38;5;241m=\u001b[39m sp\u001b[38;5;241m.\u001b[39mcsr_matrix(X)\n",
"File \u001b[0;32m~/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.11/site-packages/sklearn/base.py:600\u001b[0m, in \u001b[0;36mBaseEstimator._validate_data\u001b[0;34m(self, X, y, reset, validate_separately, **check_params)\u001b[0m\n\u001b[1;32m 597\u001b[0m out \u001b[38;5;241m=\u001b[39m X, y\n\u001b[1;32m 599\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m no_val_X \u001b[38;5;129;01mand\u001b[39;00m check_params\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mensure_2d\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mTrue\u001b[39;00m):\n\u001b[0;32m--> 600\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_check_n_features\u001b[49m\u001b[43m(\u001b[49m\u001b[43mX\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mreset\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mreset\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 602\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m out\n",
"File \u001b[0;32m~/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.11/site-packages/sklearn/base.py:400\u001b[0m, in \u001b[0;36mBaseEstimator._check_n_features\u001b[0;34m(self, X, reset)\u001b[0m\n\u001b[1;32m 397\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m\n\u001b[1;32m 399\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m n_features \u001b[38;5;241m!=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mn_features_in_:\n\u001b[0;32m--> 400\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[1;32m 401\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mX has \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mn_features\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m features, but \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__class__\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 402\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mis expecting \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mn_features_in_\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m features as input.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 403\u001b[0m )\n",
"\u001b[0;31mValueError\u001b[0m: X has 2 features, but SVC is expecting 3 features as input."
]
}
],
"source": [
"# Create grid to evaluate model\n",
"\n",
"import numpy as np\n",
"xx = np.linspace(2, 5, 100) #(100,)\n",
"yy = np.linspace(0, 2, 100) #(100,)\n",
"YY, XX = np.meshgrid(yy, xx) #(100,100) and (100,100) Replicate the data\n",
"\n",
"xy = np.vstack([XX.ravel(), YY.ravel()]).T # (10000,2)\n",
"Z = svc1.decision_function(xy).reshape(XX.shape) #(100,100)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"%matplotlib inline\n",
"\n",
"plt.scatter(Xtrain['sepal_width'], Xtrain['petal_width'], c=y1, \n",
" s=30, cmap=plt.cm.Paired)\n",
"\n",
"# plot the decision function\n",
"ax = plt.gca()\n",
"\n",
"# plot decision boundary and margins\n",
"ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1], alpha=0.5,\n",
" linestyles=['--', '-', '--'])\n",
"\n",
"# plot support vectors\n",
"ax.scatter(svc1.support_vectors_[:, 0], svc1.support_vectors_[:, 1], s=100,\n",
" linewidth=1, facecolors='none', edgecolors='k');"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Nonlinear Kernel"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<style>#sk-container-id-3 {color: black;background-color: white;}#sk-container-id-3 pre{padding: 0;}#sk-container-id-3 div.sk-toggleable {background-color: white;}#sk-container-id-3 label.sk-toggleable__label {cursor: pointer;display: block;width: 100%;margin-bottom: 0;padding: 0.3em;box-sizing: border-box;text-align: center;}#sk-container-id-3 label.sk-toggleable__label-arrow:before {content: \"▸\";float: left;margin-right: 0.25em;color: #696969;}#sk-container-id-3 label.sk-toggleable__label-arrow:hover:before {color: black;}#sk-container-id-3 div.sk-estimator:hover label.sk-toggleable__label-arrow:before {color: black;}#sk-container-id-3 div.sk-toggleable__content {max-height: 0;max-width: 0;overflow: hidden;text-align: left;background-color: #f0f8ff;}#sk-container-id-3 div.sk-toggleable__content pre {margin: 0.2em;color: black;border-radius: 0.25em;background-color: #f0f8ff;}#sk-container-id-3 input.sk-toggleable__control:checked~div.sk-toggleable__content {max-height: 200px;max-width: 100%;overflow: auto;}#sk-container-id-3 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {content: \"▾\";}#sk-container-id-3 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-3 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-3 input.sk-hidden--visually {border: 0;clip: rect(1px 1px 1px 1px);clip: rect(1px, 1px, 1px, 1px);height: 1px;margin: -1px;overflow: hidden;padding: 0;position: absolute;width: 1px;}#sk-container-id-3 div.sk-estimator {font-family: monospace;background-color: #f0f8ff;border: 1px dotted black;border-radius: 0.25em;box-sizing: border-box;margin-bottom: 0.5em;}#sk-container-id-3 div.sk-estimator:hover {background-color: #d4ebff;}#sk-container-id-3 div.sk-parallel-item::after {content: \"\";width: 100%;border-bottom: 1px solid gray;flex-grow: 1;}#sk-container-id-3 div.sk-label:hover label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-3 div.sk-serial::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: 0;}#sk-container-id-3 div.sk-serial {display: flex;flex-direction: column;align-items: center;background-color: white;padding-right: 0.2em;padding-left: 0.2em;position: relative;}#sk-container-id-3 div.sk-item {position: relative;z-index: 1;}#sk-container-id-3 div.sk-parallel {display: flex;align-items: stretch;justify-content: center;background-color: white;position: relative;}#sk-container-id-3 div.sk-item::before, #sk-container-id-3 div.sk-parallel-item::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: -1;}#sk-container-id-3 div.sk-parallel-item {display: flex;flex-direction: column;z-index: 1;position: relative;background-color: white;}#sk-container-id-3 div.sk-parallel-item:first-child::after {align-self: flex-end;width: 50%;}#sk-container-id-3 div.sk-parallel-item:last-child::after {align-self: flex-start;width: 50%;}#sk-container-id-3 div.sk-parallel-item:only-child::after {width: 0;}#sk-container-id-3 div.sk-dashed-wrapped {border: 1px dashed gray;margin: 0 0.4em 0.5em 0.4em;box-sizing: border-box;padding-bottom: 0.4em;background-color: white;}#sk-container-id-3 div.sk-label label {font-family: monospace;font-weight: bold;display: inline-block;line-height: 1.2em;}#sk-container-id-3 div.sk-label-container {text-align: center;}#sk-container-id-3 div.sk-container {/* jupyter's `normalize.less` sets `[hidden] { display: none; }` but bootstrap.min.css set `[hidden] { display: none !important; }` so we also need the `!important` here to be able to override the default hidden behavior on the sphinx rendered scikit-learn.org. See: https://github.com/scikit-learn/scikit-learn/issues/21755 */display: inline-block !important;position: relative;}#sk-container-id-3 div.sk-text-repr-fallback {display: none;}</style><div id=\"sk-container-id-3\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>SVC(degree=2, gamma=&#x27;auto&#x27;, kernel=&#x27;poly&#x27;)</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item\"><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-3\" type=\"checkbox\" checked><label for=\"sk-estimator-id-3\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">SVC</label><div class=\"sk-toggleable__content\"><pre>SVC(degree=2, gamma=&#x27;auto&#x27;, kernel=&#x27;poly&#x27;)</pre></div></div></div></div></div>"
],
"text/plain": [
"SVC(degree=2, gamma='auto', kernel='poly')"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from sklearn.svm import SVC\n",
"svc2 = SVC(kernel='poly', degree=2, gamma='auto')\n",
"svc2.fit(Xtrain, ytrain)"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
"ypred = svc2.predict(Xtest)"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[16, 0],\n",
" [ 0, 9]])"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from sklearn.metrics import confusion_matrix\n",
"\n",
"confusion_matrix(ytest, ypred)"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.11/site-packages/sklearn/base.py:450: UserWarning: X does not have valid feature names, but SVC was fitted with feature names\n",
" warnings.warn(\n"
]
},
{
"ename": "ValueError",
"evalue": "X has 2 features, but SVC is expecting 3 features as input.",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[0;32mIn [24], line 16\u001b[0m\n\u001b[1;32m 14\u001b[0m YY, XX \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39mmeshgrid(yy, xx)\n\u001b[1;32m 15\u001b[0m xy \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39mvstack([XX\u001b[38;5;241m.\u001b[39mravel(), YY\u001b[38;5;241m.\u001b[39mravel()])\u001b[38;5;241m.\u001b[39mT\n\u001b[0;32m---> 16\u001b[0m Z \u001b[38;5;241m=\u001b[39m \u001b[43msvc2\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdecision_function\u001b[49m\u001b[43m(\u001b[49m\u001b[43mxy\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241m.\u001b[39mreshape(XX\u001b[38;5;241m.\u001b[39mshape)\n\u001b[1;32m 18\u001b[0m \u001b[38;5;66;03m# plot decision boundary and margins\u001b[39;00m\n\u001b[1;32m 19\u001b[0m ax\u001b[38;5;241m.\u001b[39mcontour(XX, YY, Z, colors\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mk\u001b[39m\u001b[38;5;124m'\u001b[39m, levels\u001b[38;5;241m=\u001b[39m[\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m, \u001b[38;5;241m0\u001b[39m, \u001b[38;5;241m1\u001b[39m], alpha\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m0.5\u001b[39m,\n\u001b[1;32m 20\u001b[0m linestyles\u001b[38;5;241m=\u001b[39m[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m--\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m-\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m--\u001b[39m\u001b[38;5;124m'\u001b[39m])\n",
"File \u001b[0;32m~/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.11/site-packages/sklearn/svm/_base.py:775\u001b[0m, in \u001b[0;36mBaseSVC.decision_function\u001b[0;34m(self, X)\u001b[0m\n\u001b[1;32m 748\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mdecision_function\u001b[39m(\u001b[38;5;28mself\u001b[39m, X):\n\u001b[1;32m 749\u001b[0m \u001b[38;5;124;03m\"\"\"Evaluate the decision function for the samples in X.\u001b[39;00m\n\u001b[1;32m 750\u001b[0m \n\u001b[1;32m 751\u001b[0m \u001b[38;5;124;03m Parameters\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 773\u001b[0m \u001b[38;5;124;03m transformation of ovo decision function.\u001b[39;00m\n\u001b[1;32m 774\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m--> 775\u001b[0m dec \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_decision_function\u001b[49m\u001b[43m(\u001b[49m\u001b[43mX\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 776\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdecision_function_shape \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124movr\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mclasses_) \u001b[38;5;241m>\u001b[39m \u001b[38;5;241m2\u001b[39m:\n\u001b[1;32m 777\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m _ovr_decision_function(dec \u001b[38;5;241m<\u001b[39m \u001b[38;5;241m0\u001b[39m, \u001b[38;5;241m-\u001b[39mdec, \u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mclasses_))\n",
"File \u001b[0;32m~/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.11/site-packages/sklearn/svm/_base.py:533\u001b[0m, in \u001b[0;36mBaseLibSVM._decision_function\u001b[0;34m(self, X)\u001b[0m\n\u001b[1;32m 519\u001b[0m \u001b[38;5;124;03m\"\"\"Evaluates the decision function for the samples in X.\u001b[39;00m\n\u001b[1;32m 520\u001b[0m \n\u001b[1;32m 521\u001b[0m \u001b[38;5;124;03mParameters\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 529\u001b[0m \u001b[38;5;124;03m in the model.\u001b[39;00m\n\u001b[1;32m 530\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 531\u001b[0m \u001b[38;5;66;03m# NOTE: _validate_for_predict contains check for is_fitted\u001b[39;00m\n\u001b[1;32m 532\u001b[0m \u001b[38;5;66;03m# hence must be placed before any other attributes are used.\u001b[39;00m\n\u001b[0;32m--> 533\u001b[0m X \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_validate_for_predict\u001b[49m\u001b[43m(\u001b[49m\u001b[43mX\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 534\u001b[0m X \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_compute_kernel(X)\n\u001b[1;32m 536\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_sparse:\n",
"File \u001b[0;32m~/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.11/site-packages/sklearn/svm/_base.py:611\u001b[0m, in \u001b[0;36mBaseLibSVM._validate_for_predict\u001b[0;34m(self, X)\u001b[0m\n\u001b[1;32m 608\u001b[0m check_is_fitted(\u001b[38;5;28mself\u001b[39m)\n\u001b[1;32m 610\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m callable(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mkernel):\n\u001b[0;32m--> 611\u001b[0m X \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_validate_data\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 612\u001b[0m \u001b[43m \u001b[49m\u001b[43mX\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 613\u001b[0m \u001b[43m \u001b[49m\u001b[43maccept_sparse\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mcsr\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 614\u001b[0m \u001b[43m \u001b[49m\u001b[43mdtype\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mnp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfloat64\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 615\u001b[0m \u001b[43m \u001b[49m\u001b[43morder\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mC\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 616\u001b[0m \u001b[43m \u001b[49m\u001b[43maccept_large_sparse\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 617\u001b[0m \u001b[43m \u001b[49m\u001b[43mreset\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 618\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 620\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_sparse \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m sp\u001b[38;5;241m.\u001b[39misspmatrix(X):\n\u001b[1;32m 621\u001b[0m X \u001b[38;5;241m=\u001b[39m sp\u001b[38;5;241m.\u001b[39mcsr_matrix(X)\n",
"File \u001b[0;32m~/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.11/site-packages/sklearn/base.py:600\u001b[0m, in \u001b[0;36mBaseEstimator._validate_data\u001b[0;34m(self, X, y, reset, validate_separately, **check_params)\u001b[0m\n\u001b[1;32m 597\u001b[0m out \u001b[38;5;241m=\u001b[39m X, y\n\u001b[1;32m 599\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m no_val_X \u001b[38;5;129;01mand\u001b[39;00m check_params\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mensure_2d\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mTrue\u001b[39;00m):\n\u001b[0;32m--> 600\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_check_n_features\u001b[49m\u001b[43m(\u001b[49m\u001b[43mX\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mreset\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mreset\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 602\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m out\n",
"File \u001b[0;32m~/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.11/site-packages/sklearn/base.py:400\u001b[0m, in \u001b[0;36mBaseEstimator._check_n_features\u001b[0;34m(self, X, reset)\u001b[0m\n\u001b[1;32m 397\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m\n\u001b[1;32m 399\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m n_features \u001b[38;5;241m!=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mn_features_in_:\n\u001b[0;32m--> 400\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[1;32m 401\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mX has \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mn_features\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m features, but \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__class__\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 402\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mis expecting \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mn_features_in_\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m features as input.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 403\u001b[0m )\n",
"\u001b[0;31mValueError\u001b[0m: X has 2 features, but SVC is expecting 3 features as input."
]
},
{
"data": {
"image/png": "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jKjVYuhNv/S4PqbPQGRd/WPFdfVEA2bNR0xGToexEkQNDAmpGDz37hBVRkRE5/gdZiwWC/bv34/9+/cDaL/0ev/+/SgrKwPQftRk/vz5rvb33HMPTp48iQcffBBHjhzBX//6V7z99tv49a9/7WqzZMkSvPLKK3jjjTdw+PBh3HvvvbBarVi0KDR/1edMuxlXLHkRxuxhrmVxWUNw+a9WYsCs+V7e2X20+khc9cg6DJi1ENrIGADtp5b6Tp6DHzzxNqKSMxX3FZ3aF1c/sRF9Js12nSLRRsVi0I/uQN4f1vh1qfGQuXdh9M8fczud1H70aiamLN+kuJ+eKiIqFpMf+wdyrrsVGn0kAECM0KHflBtw9eMbzp7+IyKiUPL7PjPbtm3D1KlTOyxfsGAB1q5di4ULF6KkpATbtm1ze8+vf/1rfP/99+jbty8eeeQRLFy40O39L774Ip555hlUVlZi7Nix+Mtf/oLc3FxFNQX6PjMXamtuAmQZEdGB7fdSSE4H2qxmaCNjoInwfWrJG6fdBkerFRHRcRAvce5Ha2MNHC1WRKX1gyiqcjqWV5KjDW3NTYiIilF0So+IiLwL1P7b7zDTE3VnmCEiIqLuEbKb5hERERH1JAwzREREpGoMM0RERKRqDDNERESkagwzREREpGoMM0RERKRqDDNERESkagwzREREpGoMM0RERKRqDDNERESkagwzREREpGoMM0RERKRqDDNERESkagwzREREpGoMM0RERKRqDDNERESkagwzREREpGoMM0RERKRqDDNERESkagwzREREpGoMM0RERKRqDDNERESkagwzREREpGoMM0RERKRqDDNERESkagwzREREpGoMM0RERKRqDDNERESkagwzREREpGoMM0RERKRqDDNERESkagwzREREpGoMM0RERKRqDDNERESkagwzREREpGoMM0RERKRqDDNERESkagwzREREpGoMM0RERKRqXQozq1atQk5ODgwGA3Jzc7F3716PbadMmQJBEDq8Zs+e7WqzcOHCDutnzpzZldKIiIgozGj9fcOGDRuwZMkSrF69Grm5uVi5ciVmzJiBo0ePIjU1tUP7d999F3a73fV1XV0dxowZg5tuusmt3cyZM/H666+7vtbr9f6WRkRERGHI7yMzK1aswOLFi7Fo0SKMGDECq1evRlRUFNasWdNp+8TERKSn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\n",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"%matplotlib inline\n",
"\n",
"plt.scatter(Xtrain['sepal_width'], Xtrain['petal_width'], c=y1, \n",
" s=30, cmap=plt.cm.Paired)\n",
"\n",
"# plot the decision function\n",
"ax = plt.gca()\n",
"\n",
"# create grid to evaluate model\n",
"xx = np.linspace(2, 5, 100)\n",
"yy = np.linspace(0, 2, 100)\n",
"YY, XX = np.meshgrid(yy, xx)\n",
"xy = np.vstack([XX.ravel(), YY.ravel()]).T\n",
"Z = svc2.decision_function(xy).reshape(XX.shape)\n",
"\n",
"# plot decision boundary and margins\n",
"ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1], alpha=0.5,\n",
" linestyles=['--', '-', '--'])\n",
"\n",
"# plot support vectors\n",
"ax.scatter(svc2.support_vectors_[:, 0], svc2.support_vectors_[:, 1], s=100,\n",
" linewidth=1, facecolors='none', edgecolors='k')\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Activity 1\n",
"> Use the simulation data below to create linear classifier. \n",
"> Plot the figure like above. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"%matplotlib inline"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# from sklearn.datasets.samples_generator import make_blobs\n",
"from sklearn.datasets import make_blobs\n",
"\n",
"X, y = make_blobs(n_samples=50, centers=2,\n",
" random_state=0, cluster_std=0.60)\n",
"\n",
"# plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='autumn')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from sklearn.model_selection import train_test_split\n",
"Xtrain, Xtest, ytrain, ytest = train_test_split(X, y, random_state=2)\n",
"\n",
"from sklearn.svm import SVC\n",
"svc3 = SVC(kernel='linear',C=10)\n",
"svc3.fit(Xtrain,ytrain)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Xtrain[:,0].max()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"ypred = svc3.predict(Xtest)\n",
"ypred[:10]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"svc3.support_vectors_"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"%matplotlib inline\n",
"\n",
"plt.scatter(Xtrain[:,0], Xtrain[:,1], c=ytrain, \n",
" s=30, cmap='coolwarm')\n",
"\n",
"# plot the decision function\n",
"ax = plt.gca()\n",
"\n",
"# create grid to evaluate model\n",
"xx = np.linspace(-1, 4, 50)\n",
"yy = np.linspace(-1, 5, 50)\n",
"YY, XX = np.meshgrid(yy, xx)\n",
"xy = np.vstack([XX.ravel(), YY.ravel()]).T\n",
"Z = svc3.decision_function(xy).reshape(XX.shape)\n",
"\n",
"# plot decision boundary and margins\n",
"ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1], alpha=0.5,\n",
" linestyles=['--', '-', '--'])\n",
"# plot support vectors\n",
"ax.scatter(svc3.support_vectors_[:, 0], svc3.support_vectors_[:, 1], s=100,\n",
" linewidth=1, facecolors='none', edgecolors='k');"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Activity 2\n",
"> Use the simulation data below to create nonlinear classifier. \n",
"> Plot the figure like above. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# from sklearn.datasets.samples_generator import make_circles\n",
"from sklearn.datasets import make_circles\n",
"\n",
"X, y = make_circles(100, factor=.1, noise=.1)\n",
"plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='autumn')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from sklearn.model_selection import train_test_split\n",
"Xtrain, Xtest, ytrain, ytest = train_test_split(X, y, random_state=2)\n",
"\n",
"from sklearn.svm import SVC\n",
"svc4 = SVC(kernel='poly',degree=2,gamma='scale',C=10)\n",
"svc4.fit(Xtrain,ytrain)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"ypred = svc4.predict(Xtest)\n",
"ypred[:10]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"svc4.support_vectors_"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"%matplotlib inline\n",
"\n",
"plt.scatter(Xtrain[:,0], Xtrain[:,1], c=ytrain, \n",
" s=30, cmap='coolwarm')\n",
"\n",
"# plot the decision function\n",
"ax = plt.gca()\n",
"\n",
"# create grid to evaluate model\n",
"xx = np.linspace(-1.5, 1.5, 100)\n",
"yy = np.linspace(-1.5, 1.5, 100)\n",
"YY, XX = np.meshgrid(yy, xx)\n",
"xy = np.vstack([XX.ravel(), YY.ravel()]).T\n",
"Z = svc4.decision_function(xy).reshape(XX.shape)\n",
"\n",
"# plot decision boundary and margins\n",
"ax.contour(XX, YY, Z, colors='red', levels=[-1, 0, 1], alpha=0.5,\n",
" linestyles=['--', '-', '--'])\n",
"\n",
"# plot support vectors\n",
"ax.scatter(svc4.support_vectors_[:, 0], svc4.support_vectors_[:, 1], s=100,\n",
" linewidth=1, facecolors='none', edgecolors='k')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.0"
}
},
"nbformat": 4,
"nbformat_minor": 4
}