{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "url = \"http://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data\"\n",
    "df = pd.read_csv(url,header=None)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.preprocessing import MinMaxScaler\n",
    "\n",
    "X = MinMaxScaler().fit_transform(df.iloc[:,1:])\n",
    "Y = np.array(df.iloc[:,0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.model_selection import train_test_split"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_train, X_test, Y_train, Y_test = train_test_split(X,Y,test_size=1/3,stratify=Y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.cluster import KMeans\n",
    "kmedias = KMeans(n_clusters=15).fit(X_train)\n",
    "centros = kmedias.cluster_centers_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.metrics.pairwise import euclidean_distances\n",
    "distancias = euclidean_distances(centros)\n",
    "sigma = sum(distancias)/(centros.shape[0]-1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def mahalanobis(X,Y,S):\n",
    "    return (X-Y) @ S @ (X-Y).T\n",
    "\n",
    "S = np.cov(X,rowvar=False)\n",
    "S_inv = np.linalg.inv(S)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_mlp_train = np.zeros((X_train.shape[0], centros.shape[0]), dtype=float)\n",
    "for i in range(X_train.shape[0]):\n",
    "    for j in range(centros.shape[0]):\n",
    "        X_mlp_train[i][j] = np.exp(-mahalanobis(X_train[i],centros[j],S_inv)/(2.0*(sigma[j]**2)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "19.789408688887022"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "S = np.cov(X,rowvar=False)\n",
    "S_inv = np.linalg.inv(S)\n",
    "(X_train[0]-centros[0]) @ S_inv @ (X_train[0]-centros[0]).T"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_mlp_test = np.zeros((X_test.shape[0], centros.shape[0]), dtype=float)\n",
    "for i in range(X_test.shape[0]):\n",
    "    for j in range(centros.shape[0]):\n",
    "        X_mlp_test[i][j] = np.exp(-mahalanobis(X_test[i],centros[j],S_inv)/(2.0*(sigma[j]**2)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.preprocessing import LabelBinarizer\n",
    "etiquetas = LabelBinarizer()\n",
    "etiquetas.fit([1,2,3])\n",
    "Ymlp = etiquetas.transform(Y)\n",
    "Y_mlp_train = etiquetas.transform(Y_train)\n",
    "Y_mlp_test = etiquetas.transform(Y_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Tasa de aciertos = 58.333333333333336 %\n"
     ]
    }
   ],
   "source": [
    "from sklearn.linear_model import SGDRegressor\n",
    "adaline = SGDRegressor(max_iter=5000)\n",
    "Yp_test = np.zeros((Y_test.shape[0],3))\n",
    "for neurona_salida in range(3):\n",
    "    adaline.fit(X_mlp_train,Y_mlp_train[:,neurona_salida])\n",
    "    Yp_test[:,neurona_salida] = adaline.predict(X_mlp_test)\n",
    "aciertos = sum(np.argmax(Yp_test, axis=1) == np.argmax(Y_mlp_test,axis=1)) / Y_mlp_test.shape[0]\n",
    "print(\"Tasa de aciertos =\",aciertos*100, \"%\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Resultados\n",
    "\n",
    "||3|4|5|6|7|8|9|10|11|12|13|14|15|\n",
    "|-|-|-|-|-|-|-|-|-|-|-|-|-|-|\n",
    "|Euclídea|1|1|1|1|1|1|1|1|1|1|1|1|1|\n",
    "|Mahalanobis|0.48|0.46|0.46|0.46|0.48|0.5|0.51|0.51|0.5|0.45|0.48|0.5|0.58|"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Parte 2: MLP de salida"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.neural_network import MLPClassifier\n",
    "\n",
    "net = MLPClassifier(hidden_layer_sizes=(10),activation=\"identity\",solver=\"lbfgs\",batch_size=1,max_iter=5000,momentum=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "MLPClassifier(activation='identity', alpha=0.0001, batch_size=1, beta_1=0.9,\n",
       "       beta_2=0.999, early_stopping=False, epsilon=1e-08,\n",
       "       hidden_layer_sizes=10, learning_rate='constant',\n",
       "       learning_rate_init=0.001, max_iter=5000, momentum=0,\n",
       "       nesterovs_momentum=True, power_t=0.5, random_state=None,\n",
       "       shuffle=True, solver='lbfgs', tol=0.0001, validation_fraction=0.1,\n",
       "       verbose=False, warm_start=False)"
      ]
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net.fit(X_mlp_train,Y_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [],
   "source": [
    "Y_predict = net.predict(X_mlp_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.95"
      ]
     },
     "execution_count": 78,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sum(Y_predict == Y_test)/Y_test.shape[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tasa de acierto del 95% para tamaño de cluster 15 y distancia de Mahalanobis, usando LBFGS"
   ]
  }
 ],
 "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.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
