{"id":166217,"date":"2022-11-30T10:44:00","date_gmt":"2022-11-30T09:44:00","guid":{"rendered":"https:\/\/liora.io\/es\/?p=166217"},"modified":"2026-02-25T11:25:47","modified_gmt":"2026-02-25T10:25:47","slug":"machine-learning-clustering-dbscan","status":"publish","type":"post","link":"https:\/\/liora.io\/es\/machine-learning-clustering-dbscan","title":{"rendered":"Machine Learning &amp; Clustering: el algoritmo DBSCAN"},"content":{"rendered":"\n<p><strong>El clustering es una disciplina particular del Machine Learning que tiene como objetivo separar sus datos en grupos homog\u00e9neos con caracter\u00edsticas comunes. Es un campo muy popular en el marketing, por ejemplo, donde a menudo se intenta segmentar las bases de clientes para detectar comportamientos particulares.<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-como-funciona-el-algoritmo-dbscan\">\u00bfC\u00f3mo funciona el algoritmo DBSCAN ?<\/h2>\n\n\n\n<p>El <strong>DBSCAN<\/strong> es un <strong><a href=\"https:\/\/liora.io\/es\/que-es-un-algoritmo\">algoritmo<\/a> no supervisado<\/strong> muy conocido en materia de <strong>Clustering<\/strong>. Fue presentado en 1996 por Martin Ester, Hans-Peter Kriegel, J\u00f6rg Sander y Xiawei Xu. En este art\u00edculo detallaremos c\u00f3mo funciona y <strong>c\u00f3mo implementarlo en Python<\/strong> utilizando librer\u00edas como <a href=\"https:\/\/liora.io\/es\/scikit-learn-decubre-la-biblioteca-python\">Scikit-Learn<\/a>. Sus campos de aplicaci\u00f3n son diversos: an\u00e1lisis cartogr\u00e1fico, an\u00e1lisis de datos, segmentaci\u00f3n de una imagen, etc.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-el-principio\">El principio<\/h3>\n\n\n\n<p>Dado un conjunto de puntos y un n\u00famero entero k, el algoritmo busca <strong>dividir esos puntos en k grupos<\/strong>, llamados <strong>clusters<\/strong>, que sean <strong>homog\u00e9neos <\/strong>y <strong>compactos<\/strong>. Veamos el siguiente ejemplo:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\" style=\"margin-top:var(--wp--preset--spacing--columns);margin-bottom:var(--wp--preset--spacing--columns)\"><img decoding=\"async\" src=\"https:\/\/liora.io\/app\/uploads\/sites\/7\/2022\/11\/DBSCAN1.webp\" alt=\"\" \/><\/figure>\n\n\n\n<p>El DBSCAN es un algoritmo sencillo que define los cl\u00fasteres mediante la <b>estimaci\u00f3n de la densidad local<\/b>. Se puede dividir en 4 etapas:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Para cada observaci\u00f3n miramos el n\u00famero de puntos a una distancia m\u00e1xima \u03b5 de ella. Esta zona se denomina <b>\u03b5-vecindad de la observaci\u00f3n<\/b>.<\/li>\n\n\n\n<li>Si una observaci\u00f3n tiene al menos un cierto n\u00famero de vecinos, incluida ella misma, se considera una <b>observaci\u00f3n central<\/b>. En este caso, se ha detectado una <b>observaci\u00f3n de alta densidad<\/b>.<\/li>\n\n\n\n<li>Todas las observaciones en la vecindad de una observaci\u00f3n central pertenecen al mismo cl\u00faster. Puede haber observaciones centrales cercanas entre s\u00ed. <b>Por lo tanto, de un paso a otro, se obtiene una larga secuencia de observaciones centrales que constituyen un \u00fanico cl\u00faster.<\/b><\/li>\n\n\n\n<li>Cualquier observaci\u00f3n que no sea una observaci\u00f3n central y que no tenga ninguna observaci\u00f3n central en su vecindad se considera una <b>anomal\u00eda<\/b>.<\/li>\n<\/ul>\n\n\n\n<p>Por tanto, es necesario definir dos datos antes de utilizar DBSCAN:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>\u00bfQu\u00e9 distancia \u03b5 hay que determinar para cada observaci\u00f3n la \u03b5-vecindad? \u00bfCu\u00e1l es el n\u00famero m\u00ednimo de vecinos necesario para considerar una observaci\u00f3n como una observaci\u00f3n central?<\/em><\/p>\n<\/blockquote>\n\n\n\n<p>Estos dos datos son facilitados libremente por el usuario. A diferencia del algoritmo k-means o de la clasificaci\u00f3n jer\u00e1rquica ascendente, <b>no es necesario definir de antemano el n\u00famero de cl\u00fasteres<\/b>, lo que hace que el algoritmo sea menos r\u00edgido.<\/p>\n\n\n\n<p>Otra ventaja de DBSCAN es que tambi\u00e9n permite <b>gestionar los valores at\u00edpicos o las anomal\u00edas<\/b>. En la figura anterior se observa que el algoritmo ha determinado 3 cl\u00fasteres principales: azul, verde y amarillo. Los puntos de color morado son anomal\u00edas detectadas por el DBSCAN. Obviamente, dependiendo del valor de <b>\u03b5<\/b> y del n\u00famero de vecinos m\u00ednimos, la partici\u00f3n puede variar.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-nocion-de-distancia-y-eleccion-de-\u03b5\">Noci\u00f3n de distancia y elecci\u00f3n de \u03b5<\/h4>\n\n\n\n<p>En este algoritmo hay dos puntos clave:<\/p>\n\n\n\n<p>\u00bfCu\u00e1l es la m\u00e9trica utilizada para evaluar la distancia entre una observaci\u00f3n y sus vecinos? \u00bfCu\u00e1l es la \u03b5 ideal?<\/p>\n\n\n\n<p>En DBSCAN por lo general se utiliza la distancia euclidiana, siendo p = (p1,&#8230;.,pn) y q = (q1,&#8230;.,qn):<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter is-resized\" style=\"margin-top:var(--wp--preset--spacing--columns);margin-bottom:var(--wp--preset--spacing--columns)\"><img decoding=\"async\" src=\"https:\/\/liora.io\/app\/uploads\/sites\/7\/2022\/11\/dbscan2.webp\" alt=\"\" style=\"width:768px;height:auto\" \/><\/figure>\n\n\n\n<p>En cada observaci\u00f3n, para contar el n\u00famero de vecinos a como m\u00e1ximo una distancia <b>\u03b5<\/b>, calculamos la distancia euclidiana entre el vecino y la observaci\u00f3n y comprobamos si es inferior a <b>\u03b5<\/b>.<\/p>\n\n\n\n<p>Ahora queda saber c\u00f3mo elegir la \u00e9psilon correcta. Supongamos que en nuestro ejemplo elegimos probar el algoritmo con diferentes valores de <b>\u03b5<\/b>. Aqu\u00ed est\u00e1 el resultado:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\" style=\"margin-top:var(--wp--preset--spacing--columns);margin-bottom:var(--wp--preset--spacing--columns)\"><img decoding=\"async\" src=\"https:\/\/liora.io\/app\/uploads\/sites\/7\/2022\/11\/dbscan3.webp\" alt=\"\" \/><\/figure>\n\n\n\n<p>En los tres ejemplos, el n\u00famero m\u00ednimo de vecinos est\u00e1 fijado siempre en 5.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>Si <b>\u03b5<\/b> es demasiado peque\u00f1a, la <b>\u03b5-<\/b>vecindad es <b>demasiado peque\u00f1a<\/b> y <b>todas las observaciones<\/b> del conjunto de datos se consideran <b>anomal\u00edas<\/b>.<\/em><\/p>\n<\/blockquote>\n\n\n\n<p>Es el caso de la figura de la izquierda eps = 0,05.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>Por otro lado, si <b>\u00e9psilon es demasiado grande<\/b>, cada observaci\u00f3n contiene en su <b>\u03b5<\/b>-vecindad todas las dem\u00e1s observaciones del conjunto de datos. En consecuencia, obtenemos <b>un \u00fanico cl\u00faster<\/b>. Por tanto, es muy importante <b>calibrar adecuadamente la \u03b5<\/b> para obtener una partici\u00f3n de calidad.<\/em><\/p>\n<\/blockquote>\n\n\n\n<p>Un m\u00e9todo sencillo para optimizar la <b>\u03b5<\/b> consiste en buscar para cada observaci\u00f3n a qu\u00e9 distancia se sit\u00faa su vecino m\u00e1s cercano. Entonces basta con fijar una <b>\u03b5<\/b> que permita que una proporci\u00f3n \u00absuficientemente grande\u00bb de las observaciones tenga una distancia a su vecino m\u00e1s cercano inferior a <b>\u03b5<\/b>. Por \u00absuficientemente grande\u00bb entendemos el 90-95 % de las observaciones que deben tener al menos un vecino en su <b>\u03b5<\/b>-vecindad.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-como-implementar-el-dbscan-con-python\">\u00bfC\u00f3mo implementar el DBSCAN con Python?<\/h3>\n\n\n\n<p>El aprendizaje de DBSCAN se facilita con la <b>biblioteca Scikit-Learn<\/b>. Nuestro conjunto de datos de ejemplo se crea f\u00e1cilmente con la funci\u00f3n make_blobs de Scikit-Learn. As\u00ed es como se implementa en c\u00f3digo:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>Ahora que tenemos nuestro conjunto de datos intentaremos determinar la <strong>\u03b5 \u00f3ptima<\/strong> para obtener una <strong>mejor partici\u00f3n<\/strong> de nuestro conjunto de datos.<\/em><\/p>\n<\/blockquote>\n\n\n\n<p>Scikit-Learn proporciona una <strong><a href=\"https:\/\/scikit-learn.org\/stable\/modules\/generated\/sklearn.neighbors.NearestNeighbors.html\">clase NearestNeighbors<\/a><\/strong> que nos permite determinar los vecinos m\u00e1s cercanos de cada observaci\u00f3n, as\u00ed como las distancias. As\u00ed es como se implementa en c\u00f3digo:<\/p>\n\n\n\n<p>Este es el resultado obtenido:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\" style=\"margin-top:var(--wp--preset--spacing--columns);margin-bottom:var(--wp--preset--spacing--columns)\"><img decoding=\"async\" src=\"https:\/\/liora.io\/app\/uploads\/sites\/7\/2022\/11\/nearestneighbors.webp\" alt=\"\" \/><\/figure>\n\n\n\n<p>Como hemos visto antes, elegiremos una <b>\u03b5<\/b> para que el 90 % de las observaciones tengan una distancia de vecindad inferior a <b>\u03b5<\/b>. En nuestro ejemplo, 0,2 parece adecuado.<\/p>\n\n\n\n<p>Ahora que hemos optimizado nuestra <b>\u03b5<\/b> podemos realizar nuestra partici\u00f3n utilizando DBSCAN que ya est\u00e1 implementada en Scikit-Learn.<\/p>\n\n\n\n<p>Este es el resultado obtenido:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\" style=\"margin-top:var(--wp--preset--spacing--columns);margin-bottom:var(--wp--preset--spacing--columns)\"><img decoding=\"async\" src=\"https:\/\/liora.io\/app\/uploads\/sites\/7\/2022\/11\/DBSCAN4-1.webp\" alt=\"\" \/><\/figure>\n\n\n\n<p>Los argumentos eps y <strong>min_samples<\/strong> se utilizan para establecer los par\u00e1metros del algoritmo, es decir, la distancia <em>\u03b5<\/em> y el n\u00famero m\u00ednimo de vecinos que deben considerarse como una observaci\u00f3n central.<\/p>\n\n\n\n<p>De esta manera, el algoritmo detect\u00f3 3 cl\u00fasteres principales y algunas anomal\u00edas. Cada una de las observaciones se etiqueta con la etiqueta del cl\u00faster correspondiente (por ejemplo, 0,1,2). Las anomal\u00edas se etiquetan con -1 y, por tanto, forman una clase separada adem\u00e1s de los 3 cl\u00fasteres detectados.<\/p>\n\n\n\n<p>El uso de un algoritmo de clustering como el <strong>DBSCAN <\/strong>no es f\u00e1cil dependiendo de los datos que se tengan. Suele ser necesario repasarlos.<\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex is-content-justification-center\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/liora.io\/es\/nuestros-cursos-de-data\">Descubrir los cursos de Liora<\/a><\/div>\n<\/div>\n\n\n\n<script type=\"application\/ld+json\">\n{\n  \"@context\": \"https:\/\/schema.org\",\n  \"@type\": \"FAQPage\",\n  \"mainEntity\": [\n    {\n      \"@type\": \"Question\",\n      \"name\": \"\u00bfC\u00f3mo funciona el algoritmo DBSCAN ?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"DBSCAN (1996) es un algoritmo no supervisado de clustering que divide puntos en grupos homog\u00e9neos estimando densidad local. Etapas: 1) Para cada observaci\u00f3n, contar puntos a distancia \u2264 \u03b5 (\u03b5-vecindad). 2) Si tiene \u2265 n\u00famero m\u00ednimo de vecinos (incluida misma), es observaci\u00f3n central (alta densidad). 3) Observaciones en vecindad de central pertenecen al mismo cl\u00faster. 4) Observaciones no centrales sin ninguna central en su vecindad son anomal\u00edas. No requiere definir n\u00famero de cl\u00fasteres previamente.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"\u00bfC\u00f3mo implementar el DBSCAN con Python?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Usando Scikit-Learn: crear dataset con make_blobs. Determinar \u03b5 \u00f3ptima con NearestNeighbors (elegir \u03b5 donde ~90-95% observaciones tengan distancia vecindad &lt; \u03b5). Implementar DBSCAN con par\u00e1metros eps (\u03b5) y min_samples (n\u00famero m\u00ednimo vecinos). El algoritmo etiqueta observaciones con n\u00famero de cl\u00faster (0,1,2\u2026) y anomal\u00edas con -1.&quot;\n      }\n    }\n  ]\n}\n<\/script>\n","protected":false},"excerpt":{"rendered":"<p>El clustering es una disciplina particular del Machine Learning que tiene como objetivo separar sus datos en grupos homog\u00e9neos con caracter\u00edsticas comunes. Es un campo muy popular en el marketing, por ejemplo, donde a menudo se intenta segmentar las bases de clientes para detectar comportamientos particulares. \u00bfC\u00f3mo funciona el algoritmo DBSCAN ? El DBSCAN es [&hellip;]<\/p>\n","protected":false},"author":82,"featured_media":184163,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"editor_notices":[],"footnotes":""},"categories":[2440],"class_list":["post-166217","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-data-ia"],"acf":[],"_links":{"self":[{"href":"https:\/\/liora.io\/es\/wp-json\/wp\/v2\/posts\/166217","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/liora.io\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/liora.io\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/liora.io\/es\/wp-json\/wp\/v2\/users\/82"}],"replies":[{"embeddable":true,"href":"https:\/\/liora.io\/es\/wp-json\/wp\/v2\/comments?post=166217"}],"version-history":[{"count":3,"href":"https:\/\/liora.io\/es\/wp-json\/wp\/v2\/posts\/166217\/revisions"}],"predecessor-version":[{"id":184166,"href":"https:\/\/liora.io\/es\/wp-json\/wp\/v2\/posts\/166217\/revisions\/184166"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/liora.io\/es\/wp-json\/wp\/v2\/media\/184163"}],"wp:attachment":[{"href":"https:\/\/liora.io\/es\/wp-json\/wp\/v2\/media?parent=166217"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/liora.io\/es\/wp-json\/wp\/v2\/categories?post=166217"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}