From 9546fabe3d5199e77f9c4237a75fde473a960609 Mon Sep 17 00:00:00 2001 From: MaDerniszator Date: Fri, 20 Dec 2024 12:24:06 +0400 Subject: [PATCH] =?UTF-8?q?=D0=B0=D0=B0=D0=B0=D0=B0=D0=B0=D0=B0=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lab_4/lab_products_clustering.ipynb | 200 +++++++++++++++++++++++++--- 1 file changed, 185 insertions(+), 15 deletions(-) diff --git a/Lab_4/lab_products_clustering.ipynb b/Lab_4/lab_products_clustering.ipynb index e398c2e..a029afe 100644 --- a/Lab_4/lab_products_clustering.ipynb +++ b/Lab_4/lab_products_clustering.ipynb @@ -32,10 +32,129 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "id": "dab41ace", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "RangeIndex: 162313 entries, 0 to 162312\n", + "Data columns (total 5 columns):\n", + " # Column Non-Null Count Dtype \n", + "--- ------ -------------- ----- \n", + " 0 category 162313 non-null object \n", + " 1 sub_category 162313 non-null object \n", + " 2 href 162313 non-null object \n", + " 3 items 162280 non-null object \n", + " 4 price 162282 non-null float64\n", + "dtypes: float64(1), object(4)\n", + "memory usage: 6.2+ MB\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
categorysub_categoryhrefitemsprice
0GroceriesFruits & Vegetableshttps://www.jiomart.com/c/groceries/fruits-veg...Fresh Dates (Pack) (Approx 450 g - 500 g)109.0
1GroceriesFruits & Vegetableshttps://www.jiomart.com/c/groceries/fruits-veg...Tender Coconut Cling Wrapped (1 pc) (Approx 90...49.0
2GroceriesFruits & Vegetableshttps://www.jiomart.com/c/groceries/fruits-veg...Mosambi 1 kg69.0
3GroceriesFruits & Vegetableshttps://www.jiomart.com/c/groceries/fruits-veg...Orange Imported 1 kg125.0
4GroceriesFruits & Vegetableshttps://www.jiomart.com/c/groceries/fruits-veg...Banana Robusta 6 pcs (Box) (Approx 800 g - 110...44.0
\n", + "
" + ], + "text/plain": [ + " category sub_category \\\n", + "0 Groceries Fruits & Vegetables \n", + "1 Groceries Fruits & Vegetables \n", + "2 Groceries Fruits & Vegetables \n", + "3 Groceries Fruits & Vegetables \n", + "4 Groceries Fruits & Vegetables \n", + "\n", + " href \\\n", + "0 https://www.jiomart.com/c/groceries/fruits-veg... \n", + "1 https://www.jiomart.com/c/groceries/fruits-veg... \n", + "2 https://www.jiomart.com/c/groceries/fruits-veg... \n", + "3 https://www.jiomart.com/c/groceries/fruits-veg... \n", + "4 https://www.jiomart.com/c/groceries/fruits-veg... \n", + "\n", + " items price \n", + "0 Fresh Dates (Pack) (Approx 450 g - 500 g) 109.0 \n", + "1 Tender Coconut Cling Wrapped (1 pc) (Approx 90... 49.0 \n", + "2 Mosambi 1 kg 69.0 \n", + "3 Orange Imported 1 kg 125.0 \n", + "4 Banana Robusta 6 pcs (Box) (Approx 800 g - 110... 44.0 " + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "import pandas as pd\n", "import matplotlib.pyplot as plt\n", @@ -44,9 +163,10 @@ "from sklearn.metrics import silhouette_score\n", "from scipy.cluster.hierarchy import dendrogram, linkage\n", "import seaborn as sns\n", + "from sklearn.preprocessing import LabelEncoder\n", "\n", "# Загрузка данных\n", - "df = pd.read_csv('your_dataset_path.csv')\n", + "df = pd.read_csv('../data/jio_mart_items.csv')\n", "df.info() # Проверка структуры датасета\n", "df.head()" ] @@ -61,23 +181,26 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "id": "14f5eb76", "metadata": {}, "outputs": [], "source": [ - "# Обработка пропущенных значений\n", - "df.dropna(inplace=True)\n", + "# Преобразуем столбец 'items' в числовые категории\n", + "label_encoder = LabelEncoder()\n", + "df['items_encoded'] = label_encoder.fit_transform(df['items'])\n", "\n", - "# Проверим распределение числовых признаков\n", - "df.describe()\n", + "# Указываем числовые столбцы для нормализации\n", + "numeric_features = ['items_encoded', 'price']\n", "\n", "# Нормализация данных\n", "from sklearn.preprocessing import StandardScaler\n", "scaler = StandardScaler()\n", - "numeric_features = ['items', 'price']\n", "df_scaled = scaler.fit_transform(df[numeric_features])\n", - "df_scaled = pd.DataFrame(df_scaled, columns=numeric_features)" + "\n", + "# Преобразуем обратно в DataFrame для удобства\n", + "df_scaled = pd.DataFrame(df_scaled, columns=numeric_features)\n", + "df_scaled = df_scaled.dropna()" ] }, { @@ -90,10 +213,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "id": "c23ca5db", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjsAAAHHCAYAAABZbpmkAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAARRtJREFUeJzt3Xl4FFXe/v+7AyRhSToGCEk0QABlB0UlMjMKaJSgxgXGBXFYB1xABVwwzmAAR4Pi44KDoH4F1ADj4IMgqFG2gEsEJGQQEEyYACIJW8wCMfv5/cEv/dBkIcGku1O8X9fV12WfOl39OV1t+qbqVJXNGGMEAABgUV7uLgAAAKA+EXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXbQICxatEg2m83pERQUpIEDB+rzzz93d3kA6tmAAQOc/v8PDAzU1VdfrQULFqisrKxC/8TERA0ZMkTBwcHy9vZWUFCQoqOjtXz58krX/+OPP8pms8nX11fZ2dn1PBq4GmEHDcrMmTP1wQcf6P3339dTTz2lY8eO6eabb9bq1avdXRqAenbJJZfogw8+0AcffKBp06appKREY8eO1TPPPOPULzY2VgMHDtTOnTv1wAMPaP78+XryySd18uRJDR06VEuWLKmw7vj4eAUHB0uSPvroI5eMB65j40agaAgWLVqk0aNHa+vWrbrqqqsc7b/++qvatGmju+66S4sXL3ZjhQDq04ABA3T8+HHt3LnT0Zafn6/OnTvr119/1a+//qomTZroo48+0l133aU///nPWrJkiZo0aeK0ni+++ELFxcW69dZbHW3GGHXo0EFDhgxRenq6fv31V23YsMFlY0P9Y88OGrSAgAA1bdpUjRs3drTt379fNptNixYtcuo7YcIE2Ww2jRo1ytG2fPly9e3bV4GBgWratKm6dOmiF198UeX/BtiwYYNsNps+/vjjCu+9ZMkS2Ww2JSUlSZJ27NihUaNGqUOHDvL19VVwcLDGjBmjEydOVFp7+/btKxyas9lsSkxMdOpzZr2StGzZMtlsNrVv397RtnfvXl1//fUKDg6Wj4+PwsLC9OCDDyorK8vRp6ioSM8++6yuvPJK2e12NW/eXNdee22FP+rln9/LL79coeYePXpowIABTm0DBgyo0LZ161bHeM508uRJPf744+rQoYOaNGniNO7jx49X+jmdrbLP7OzPrT7GmpiYKJvNVum/+lu0aOG0ncoPu37//fdVjuPsz23kyJHy9fXVjz/+6NRv0KBBuuiii3T48OEq11U+jqoeZ2+fo0ePauzYsWrTpo18fX3Vu3dvvffeexXWW1ZWptdff109e/aUr6+vWrduraioqArjquwwc2Xvm52drUmTJiksLEw+Pj7q1KmTXnzxxUoPQ9VEs2bNdM011+jUqVM6duyYJGnatGkKDAzUggULKgQd6fTneWbQkaRvvvlG+/fv17333qt7771XmzZt0qFDh86rJnimxufuAniOnJwcHT9+XMYYHT16VG+88YZOnjyp+++/v9rXpaWl6Z133qnQnpubq4iICI0cOVJNmjRRQkKCnn76aTVu3FiPP/64BgwYoLCwMC1evFh33nmn02sXL16sjh07ql+/fpKkNWvW6L///a9Gjx6t4OBg7dq1S2+//bZ27dql7777rsIPvyRde+21Gj9+vKTTcwZeeOGFasdRUlKiv/3tbxXaT506pUsuuUTR0dHy9/fXzp07NXfuXP3yyy9atWqVY6z/7//9Pw0bNkzjxo1TXl6e3n33XQ0aNEhbtmzR5ZdfXu1718bUqVMrbX/yySc1f/58jR07Vn/84x/VpEkTLV++vNIwWZ0bb7xRI0aMkHQ6WM2ZM8dpuSvHWldef/11rV+/XiNHjlRSUpIaNWqkt956S19++aU++OADhYaGnnMdw4YN08033+zUFhMT4/T8t99+04ABA5SWlqaJEycqPDxcy5Yt06hRo5Sdna3HHnvM0Xfs2LFatGiRBg8erL/+9a8qKSnRV199pe+++85pD2u5V199Va1atZIkPf/8807L8vPz1b9/f/3yyy964IEH1LZtW3377beKiYlRRkaGXnvttZp+VE7++9//qlGjRgoICFBqaqr27NmjMWPGyM/Pr8brKP9/+eqrr1aPHj3UrFkzLV26VE8++eR51QQPZIAGYOHChUZShYePj49ZtGiRU9/09HQjySxcuNDRdvfdd5sePXqYsLAwM3LkyGrfq1u3bubWW291PI+JiTE+Pj4mOzvb0Xb06FHTuHFjExsb62jLz8+vsK6lS5caSWbTpk0Vll188cVm9OjRjucbNmwwksyGDRscbe3atXOq98033zQ+Pj5m4MCBpl27dtWO4+GHHzYtWrRwPC8pKTGFhYVOfX799VfTpk0bM2bMGEdb+ec3e/bsCuvs3r276d+/v1Nb//79ndo+++wzI8lERUWZs//EhISEmEGDBjm1xcbGGknm2LFj1Y7HGGOKioqMJDNx4kRH27Jlyyp8bvUx1vLts2zZsgp9mzdv7rSdyr+vW7durXIsZ39uxhjzxRdfGEnmH//4h/nvf/9rWrRoYe64444q13E+43jttdeMJBMfH+9oKyoqMv369TMtWrQwubm5xhhj1q9fbySZRx99tMI6y8rKnJ6/8847RpI5cOBAleN77rnnTPPmzc1PP/3k9Nqnn37aNGrUyBw8eLDaMfbv39906dLFHDt2zBw7dsz8+OOP5tFHHzWSTHR0tDHGmJUrVxpJ5tVXX612XWcqKioyLVu2NH/7298cbffdd5/p3bt3jdcBz8dhLDQoc+fO1Zo1a7RmzRrFx8dr4MCB+utf/1rlGRaStG3bNi1btkxxcXHy8qr8K3/8+HEdOnRIixYtUlpamq677jrHshEjRqiwsNDp8MWHH36okpISpz1KTZs2dfx3QUGBjh8/rmuuuUaSlJycXOE9i4qK5OPjU+Ox5+fna+bMmZo4caLatm1baZ+cnBwdOXJE69at06effuo0jkaNGsnb21vS6cMTWVlZKikp0VVXXVVpfefDGKOYmBgNHTpUERERFZbn5eWpZcuW573+goICSZKvr2+1/Wo71vz8fB0/ftzpUVpaWum68/LyKvStSvmeyLy8vBqN76abbtIDDzygmTNnasiQIfL19dVbb71Vo9fW1Geffabg4GANGzbM0dakSRM9+uijOnnypDZu3ChJ+t///V/ZbDbFxsZWWMfZeymLiookqdrv87Jly3TttdfqoosucvrsIiMjVVpaqk2bNp2z9j179qh169Zq3bq1unbtqjfeeEO33HKLFixYIOn0Hj1Jtdqr8/nnn+vEiRNOn8ewYcP0n//8R7t27arxeuDZCDtoUPr27avIyEhFRkZq+PDh+vTTT9WtWzdNnDjR8Qf3bE8//bSuvfbaCsfpyxUUFKh169YKCwvTmDFj9OSTTzrtvu7SpYuuvvpqpwnQixcv1jXXXKNOnTo52rKysvTYY4+pTZs2atq0qVq3bq3w8HBJp3/0zpaTk6MWLVrUeOyvvPKKCgoKKpx5cqZBgwYpODhYkZGR6tq1qz788EOn5e+995569eolX19ftWzZUq1bt9ann35aaX3nY/Hixdq1a1eVh+P69eunjz/+WB999JEyMjJ0/Phx5efn13j95cHCbrefs29txhobG+v4ES1/7Nmzp9L1jhkzpkLfU6dOVdo3MjJSrVu3lr+/vy666CI9/PDDVfYt9/LLLyswMFApKSmaM2eOgoKCzjnW2jhw4IAuvfTSCsG/a9eujuWStG/fPoWGhiowMPCc6yw/Vbu673NqaqoSEhIqfHaRkZGSTs8jOpf27dtrzZo1Wrt2rb7++mtlZmZq9erVjkNn/v7+klTjcCmdPgsrPDxcPj4+SktLU1pamjp27KhmzZpx0oOFMGcHDZqXl5cGDhyo119/XampqerevbvT8i+//FJr1651TCKujLe3t9asWaP8/Hx99dVXevHFFxUWFqYHHnjA0WfEiBF67LHHdOjQIRUWFuq7777TP//5T6f13H333fr222/15JNP6vLLL1eLFi1UVlamqKioChMws7KyVFRU5DjV9VyOHz+u2bNnKyYmptofnzfeeEPHjx/X7t27FRcXpwcffFDx8fGSTv9RHzVqlO644w49+eSTCgoKUqNGjRQXF6d9+/bVqI7qFBUVadq0aRo7dqwuu+yySvu8/fbbGjZsmO66667zeo/9+/dLktPk7MrUdqzjx4+vUNO4ceMqXfezzz6ra6+91qktOjq60r5z587VZZddpsLCQiUmJjomQr/55ptV1r59+3bHD/8PP/zgtMfBU2VmZqpFixZq3rx5lX3Kysp044036qmnnqp0eVXfmTM1b97cEY4q06VLF0mnP7eayM3N1apVq1RQUKBLL720wvIlS5bo+eefr3S+HRoWwg4avJKSEkmnz/Q5kzFGTz/9tO68807H4aTKeHl5Of6A3nbbbcrKytKzzz7rFHbuvfdeTZkyRUuXLtVvv/2mJk2a6J577nEs//XXX7Vu3TrNmDFDzz77rKM9NTW10vfcvXu3pP/71/S5/OMf/5Cfn5/T5NHKXH311ZKkwYMHKygoSCNGjNDf/vY3de3aVR999JE6dOig5cuXO/3xruwwxfl48803dfToUU2fPr3KPu3bt1d8fLx69uypMWPG6I477tD777+vDz74oEbvUX4WUGWTY89U27FeeumlFX5Eq/rh7tmzZ4W+jRo1qrRv3759HbXecsst+s9/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iQolJSXKysqyzHeiPOgcOHBAa9ascdqrU5mIiAiVlJRo//79rinQhTp06KBWrVo5vu8XwvaXpK+++kp79+49598Dqf62P2Gnnnl7e+vKK6/UunXrHG1lZWVat26d+vXr58bK6ocxRhMnTtTHH3+s9evXKzw8/JyvSUlJkSSFhITUc3Wud/LkSe3bt08hISG68sor1aRJE6fvwt69e3Xw4EHLfRcWLlyooKAg3XLLLdX2s/K2Dw8PV3BwsNP2zs3N1ebNmx3bu1+/fsrOzta2bdscfdavX6+ysjJHEGzIyoNOamqq1q5dq5YtW57zNSkpKfLy8qpweMcKDh06pBMnTji+71bf/uXeffddXXnllerdu/c5+9bb9q/3KdAw//rXv4yPj49ZtGiR2b17txk/frwJCAgwmZmZ7i6tzj300EPGbrebxMREk5GR4Xjk5+cbY4xJS0szM2fONN9//71JT083K1euNB06dDDXXXedmyuvG48//rhJTEw06enp5ptvvjGRkZGmVatW5ujRo8YYYx588EHTtm1bs379evP999+bfv36mX79+rm56rpVWlpq2rZta6ZOnerUbsVtn5eXZ7Zv3262b99uJJlXXnnFbN++3XG20axZs0xAQIBZuXKl2bFjh7n99ttNeHi4+e233xzriIqKMldccYXZvHmz+frrr82ll15qhg0b5q4h1Up14y8qKjK33XabueSSS0xKSorT34PCwkJjjDHffvutefXVV01KSorZt2+fiY+PN61btzYjRoxw88hqprrx5+XlmSeeeMIkJSWZ9PR0s3btWtOnTx9z6aWXmoKCAsc6rLr9y+Xk5JhmzZqZefPmVXi9K7c/YcdF3njjDdO2bVvj7e1t+vbta7777jt3l1QvJFX6WLhwoTHGmIMHD5rrrrvOBAYGGh8fH9OpUyfz5JNPmpycHPcWXkfuueceExISYry9vc3FF19s7rnnHpOWluZY/ttvv5mHH37YXHTRRaZZs2bmzjvvNBkZGW6suO598cUXRpLZu3evU7sVt/2GDRsq/b6PHDnSGHP69PNp06aZNm3aGB8fH3PDDTdU+FxOnDhhhg0bZlq0aGH8/f3N6NGjTV5enhtGU3vVjT89Pb3KvwcbNmwwxhizbds2ExERYex2u/H19TVdu3Y1L7zwglMY8GTVjT8/P9/cdNNNpnXr1qZJkyamXbt2Zty4cRX+kWvV7V/urbfeMk2bNjXZ2dkVXu/K7W8zxpi63VcEAADgOZizAwAALI2wAwAALI2wAwAALI2wAwAALI2wAwAALI2wAwAALI2wAwAALI2wAwAALI2wA6DBGTVqlGw2m2w2m7y9vdWpUyfNnDlTJSUlkk7fo+3tt99WRESEWrRooYCAAF111VV67bXXlJ+fL0natWuXhg4dqvbt28tms+m1115z44gA1CfCDoAGKSoqShkZGUpNTdXjjz+u6dOna/bs2ZKkv/zlL5o0aZJuv/12bdiwQSkpKZo2bZpWrlypL7/8UpKUn5+vDh06aNasWZa6wzSAirhdBIAGZ9SoUcrOztaKFSscbTfddJPy8vI0efJk3XPPPVqxYoVuv/12p9cZY5Sbmyu73e7U3r59e02aNEmTJk1yQfUAXI09OwAsoWnTpioqKtLixYvVuXPnCkFHkmw2W4WgA8D6CDsAGjRjjNauXasvvvhC119/vVJTU9W5c2d3lwXAgxB2ADRIq1evVosWLeTr66vBgwfrnnvu0fTp08WReQBna+zuAgDgfAwcOFDz5s2Tt7e3QkND1bjx6T9nl112mfbs2ePm6gB4EvbsAGiQmjdvrk6dOqlt27aOoCNJ9913n3766SetXLmywmuMMcrJyXFlmQA8AGEHgKXcfffduueeezRs2DC98MIL+v7773XgwAGtXr1akZGR2rBhgySpqKhIKSkpSklJUVFRkX755RelpKQoLS3NzSMAUNc49RxAg1PZqednKisr09tvv60FCxZo165daty4sS699FKNGDFC48aNU9OmTbV//36Fh4dXeG3//v2VmJhYvwMA4FKEHQAAYGkcxgIAAJZG2AEAAJZG2AEAAJZG2AEAAJZG2AEAAJZG2AEAAJZG2AEAAJZG2AEAAJZG2AEAAJZG2AEAAJZG2AEAAJZG2AEAAJb2/wGpij0KLp4xvQAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "# Применение PCA для понижения размерности\n", "pca = PCA(n_components=2)\n", @@ -117,10 +251,28 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "id": "cf6663df", "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[17], line 9\u001b[0m\n\u001b[0;32m 7\u001b[0m kmeans\u001b[38;5;241m.\u001b[39mfit(reduced_data)\n\u001b[0;32m 8\u001b[0m inertia\u001b[38;5;241m.\u001b[39mappend(kmeans\u001b[38;5;241m.\u001b[39minertia_)\n\u001b[1;32m----> 9\u001b[0m silhouette_scores\u001b[38;5;241m.\u001b[39mappend(\u001b[43msilhouette_score\u001b[49m\u001b[43m(\u001b[49m\u001b[43mreduced_data\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mkmeans\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mlabels_\u001b[49m\u001b[43m)\u001b[49m)\n\u001b[0;32m 11\u001b[0m \u001b[38;5;66;03m# Построение графиков\u001b[39;00m\n\u001b[0;32m 12\u001b[0m plt\u001b[38;5;241m.\u001b[39mfigure(figsize\u001b[38;5;241m=\u001b[39m(\u001b[38;5;241m14\u001b[39m, \u001b[38;5;241m5\u001b[39m))\n", + "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\sklearn\\utils\\_param_validation.py:216\u001b[0m, in \u001b[0;36mvalidate_params..decorator..wrapper\u001b[1;34m(*args, **kwargs)\u001b[0m\n\u001b[0;32m 210\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m 211\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m config_context(\n\u001b[0;32m 212\u001b[0m skip_parameter_validation\u001b[38;5;241m=\u001b[39m(\n\u001b[0;32m 213\u001b[0m prefer_skip_nested_validation \u001b[38;5;129;01mor\u001b[39;00m global_skip_validation\n\u001b[0;32m 214\u001b[0m )\n\u001b[0;32m 215\u001b[0m ):\n\u001b[1;32m--> 216\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m func(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m 217\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m InvalidParameterError \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[0;32m 218\u001b[0m \u001b[38;5;66;03m# When the function is just a wrapper around an estimator, we allow\u001b[39;00m\n\u001b[0;32m 219\u001b[0m \u001b[38;5;66;03m# the function to delegate validation to the estimator, but we replace\u001b[39;00m\n\u001b[0;32m 220\u001b[0m \u001b[38;5;66;03m# the name of the estimator by the name of the function in the error\u001b[39;00m\n\u001b[0;32m 221\u001b[0m \u001b[38;5;66;03m# message to avoid confusion.\u001b[39;00m\n\u001b[0;32m 222\u001b[0m msg \u001b[38;5;241m=\u001b[39m re\u001b[38;5;241m.\u001b[39msub(\n\u001b[0;32m 223\u001b[0m \u001b[38;5;124mr\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mparameter of \u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124mw+ must be\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m 224\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mparameter of \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mfunc\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__qualname__\u001b[39m\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m must be\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m 225\u001b[0m \u001b[38;5;28mstr\u001b[39m(e),\n\u001b[0;32m 226\u001b[0m )\n", + "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\sklearn\\metrics\\cluster\\_unsupervised.py:139\u001b[0m, in \u001b[0;36msilhouette_score\u001b[1;34m(X, labels, metric, sample_size, random_state, **kwds)\u001b[0m\n\u001b[0;32m 137\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m 138\u001b[0m X, labels \u001b[38;5;241m=\u001b[39m X[indices], labels[indices]\n\u001b[1;32m--> 139\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m np\u001b[38;5;241m.\u001b[39mmean(silhouette_samples(X, labels, metric\u001b[38;5;241m=\u001b[39mmetric, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwds))\n", + "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\sklearn\\utils\\_param_validation.py:189\u001b[0m, in \u001b[0;36mvalidate_params..decorator..wrapper\u001b[1;34m(*args, **kwargs)\u001b[0m\n\u001b[0;32m 187\u001b[0m global_skip_validation \u001b[38;5;241m=\u001b[39m get_config()[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mskip_parameter_validation\u001b[39m\u001b[38;5;124m\"\u001b[39m]\n\u001b[0;32m 188\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m global_skip_validation:\n\u001b[1;32m--> 189\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m func(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m 191\u001b[0m func_sig \u001b[38;5;241m=\u001b[39m signature(func)\n\u001b[0;32m 193\u001b[0m \u001b[38;5;66;03m# Map *args/**kwargs to the function signature\u001b[39;00m\n", + "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\sklearn\\metrics\\cluster\\_unsupervised.py:303\u001b[0m, in \u001b[0;36msilhouette_samples\u001b[1;34m(X, labels, metric, **kwds)\u001b[0m\n\u001b[0;32m 299\u001b[0m kwds[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmetric\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m metric\n\u001b[0;32m 300\u001b[0m reduce_func \u001b[38;5;241m=\u001b[39m functools\u001b[38;5;241m.\u001b[39mpartial(\n\u001b[0;32m 301\u001b[0m _silhouette_reduce, labels\u001b[38;5;241m=\u001b[39mlabels, label_freqs\u001b[38;5;241m=\u001b[39mlabel_freqs\n\u001b[0;32m 302\u001b[0m )\n\u001b[1;32m--> 303\u001b[0m results \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mzip\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mpairwise_distances_chunked\u001b[49m\u001b[43m(\u001b[49m\u001b[43mX\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mreduce_func\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mreduce_func\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwds\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 304\u001b[0m intra_clust_dists, inter_clust_dists \u001b[38;5;241m=\u001b[39m results\n\u001b[0;32m 305\u001b[0m intra_clust_dists \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39mconcatenate(intra_clust_dists)\n", + "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\sklearn\\metrics\\pairwise.py:2261\u001b[0m, in \u001b[0;36mpairwise_distances_chunked\u001b[1;34m(X, Y, reduce_func, metric, n_jobs, working_memory, **kwds)\u001b[0m\n\u001b[0;32m 2259\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m reduce_func \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m 2260\u001b[0m chunk_size \u001b[38;5;241m=\u001b[39m D_chunk\u001b[38;5;241m.\u001b[39mshape[\u001b[38;5;241m0\u001b[39m]\n\u001b[1;32m-> 2261\u001b[0m D_chunk \u001b[38;5;241m=\u001b[39m \u001b[43mreduce_func\u001b[49m\u001b[43m(\u001b[49m\u001b[43mD_chunk\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43msl\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mstart\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 2262\u001b[0m _check_chunk_size(D_chunk, chunk_size)\n\u001b[0;32m 2263\u001b[0m \u001b[38;5;28;01myield\u001b[39;00m D_chunk\n", + "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\sklearn\\metrics\\cluster\\_unsupervised.py:180\u001b[0m, in \u001b[0;36m_silhouette_reduce\u001b[1;34m(D_chunk, start, labels, label_freqs)\u001b[0m\n\u001b[0;32m 178\u001b[0m sample_weights \u001b[38;5;241m=\u001b[39m D_chunk[i]\n\u001b[0;32m 179\u001b[0m sample_labels \u001b[38;5;241m=\u001b[39m labels\n\u001b[1;32m--> 180\u001b[0m cluster_distances[i] \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[43mnp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mbincount\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 181\u001b[0m \u001b[43m \u001b[49m\u001b[43msample_labels\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mweights\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43msample_weights\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mminlength\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mlen\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mlabel_freqs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 182\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 184\u001b[0m \u001b[38;5;66;03m# intra_index selects intra-cluster distances within cluster_distances\u001b[39;00m\n\u001b[0;32m 185\u001b[0m end \u001b[38;5;241m=\u001b[39m start \u001b[38;5;241m+\u001b[39m n_chunk_samples\n", + "\u001b[1;31mKeyboardInterrupt\u001b[0m: " + ] + } + ], "source": [ "# Оценка инерции для выбора числа кластеров\n", "inertia = []\n", @@ -210,7 +362,25 @@ ] } ], - "metadata": {}, + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.10.8" + } + }, "nbformat": 4, "nbformat_minor": 5 }