<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Personal Project on Matias Di Bernardo</title><link>https://dibernardo.netlify.app/es/tags/personal-project/</link><description>Recent content in Personal Project on Matias Di Bernardo</description><generator>Hugo -- gohugo.io</generator><language>es</language><copyright>Matías Di Bernardo</copyright><lastBuildDate>Sat, 12 Aug 2023 00:00:00 +0000</lastBuildDate><atom:link href="https://dibernardo.netlify.app/es/tags/personal-project/index.xml" rel="self" type="application/rss+xml"/><item><title>Z-Plane Visualizer</title><link>https://dibernardo.netlify.app/es/p/z-plane-visualizer/</link><pubDate>Sat, 12 Aug 2023 00:00:00 +0000</pubDate><guid>https://dibernardo.netlify.app/es/p/z-plane-visualizer/</guid><description>&lt;img src="https://dibernardo.netlify.app/p/z-plane-visualizer/frontz.PNG" alt="Featured image of post Z-Plane Visualizer" />&lt;p>En el curso de &lt;em>Procesamiento Digital de Señales&lt;/em> (DSP) en la UNTREF, exploramos el plano Z para el diseño de filtros con variables discretas. Durante la clase, el profesor presentó una herramienta construida en MatLab que visualiza los gráficos de transferencia y fase en relación con las posiciones de los ceros y polos en el plano Z.&lt;/p>
&lt;p>Inspirado en esto, decidí recrear esta herramienta en Python. Aprovechando mi experiencia con la biblioteca PyGame, logré construir una aplicación en tiempo real que permite mover los polos y ceros, permitiendo a los usuarios ver cómo cambia la función de transferencia en tiempo real.&lt;/p>
&lt;h2 id="cómo-funciona">Cómo Funciona
&lt;/h2>&lt;p>Primero, mapeo las posiciones de los píxeles en el plano Z a coordenadas de acuerdo con la representación del círculo unitario. Luego, construyo la función de transferencia, donde cada cero $z_{n}$ es un término en el numerador y cada polo $z_{i}$ es un término en el denominador. Con la función de transferencia $H(z)$, puedo graficar tanto el magnitud como el gráfico de fase, que también son representaciones mapeadas de la respuesta normalizada dentro de la aplicación.&lt;/p>
$$
H(z) = \frac{\sum_{n=0}^{N} (z - z_{n})}{\sum_{i=0}^{N} (z - z_{i})}
$$&lt;p>Cada fotograma recalcula la función de transferencia. El programa funciona de manera eficiente porque almaceno los ceros y polos en arreglos, lo que permite cálculos más rápidos gracias a numpy, que ya está altamente optimizado. Esto permite visualizar los cambios en tiempo real y proporciona una comprensión más intuitiva del comportamiento del plano Z. El siguiente fragmento de código muestra como se calcula la magnitud y fase utilizando exponenciales complejas.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">e&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">w&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">root&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="n">j&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">w&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">root&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">transfer_function&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">zeros&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">poles&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">w&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">linspace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pi&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pi&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">RES&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">zero&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">zeros&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">num&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">w&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">zero&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">pole&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">poles&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">den&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">w&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">pole&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">H_z&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">num&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">den&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">mag&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">abs&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">H_z&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ang&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">angle&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">H_z&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">mag&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ang&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Este proyecto está diseñado como material educativo, proporcionando a los estudiantes una herramienta práctica para comprender mejor las interacciones entre los polos y ceros en el plano Z. No está destinado como una herramienta profesional para el diseño de filtros.&lt;/p>
&lt;h2 id="funcionalidad">Funcionalidad
&lt;/h2>&lt;p>La aplicación ofrece las siguientes características:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>Mostrar y mover polos/ceros&lt;/strong>: Los usuarios pueden seleccionar y mover los polos y ceros en el plano Z. Cuando la opción de simetría está activa, todos los polos y ceros seleccionados o movidos se colocan de manera simétrica respecto al eje imaginario.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Orden&lt;/strong>: Los usuarios pueden ajustar el orden de los polos y ceros desplazando la rueda del mouse. El orden puede incrementarse o disminuirse, con soporte hasta un orden de 4. El color de cada polo o cero cambia según su orden.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Información&lt;/strong>: Al pasar el cursor sobre un polo o cero, se muestra información sobre su posición, simetría y orden.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Zoom&lt;/strong>: El usuario puede acercar o alejar el plano Z usando los botones de más y menos.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Eliminar&lt;/strong>: El ícono de la papelera elimina todos los polos y ceros del plano. Los usuarios también pueden eliminar polos o ceros individuales haciendo clic derecho sobre ellos.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Gráfico de Magnitud&lt;/strong>: El espectro de magnitud mostrado en la aplicación está normalizado. Esta decisión asegura que el enfoque permanezca en la forma de la magnitud, haciendo que el gráfico sea visualmente significativo para los usuarios. Sin embargo, no captura la diferencia en los valores máximos.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Gráfico de Fase&lt;/strong>: La fase se muestra sin envolver entre $-\pi$ y $\pi$.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="demo">Demo
&lt;/h2>&lt;p>Aquí tienes una demostración rápida de la aplicación en acción:&lt;/p>
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
&lt;iframe src="https://player.vimeo.com/video/1045497647" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="vimeo video" webkitallowfullscreen mozallowfullscreen allowfullscreen>&lt;/iframe>
&lt;/div>
&lt;p>El código fuente de este proyecto se encuentra en este &lt;a class="link" href="https://github.com/MatiasDiBernardo/Z-Plane_Visualizer" target="_blank" rel="noopener"
>repositorio&lt;/a>.&lt;/p></description></item><item><title>IA aprende a jugar 2048</title><link>https://dibernardo.netlify.app/es/p/ia-aprende-a-jugar-2048/</link><pubDate>Fri, 17 Feb 2023 00:00:00 +0000</pubDate><guid>https://dibernardo.netlify.app/es/p/ia-aprende-a-jugar-2048/</guid><description>&lt;img src="https://dibernardo.netlify.app/p/ai-learns-to-play-2048-game/game_img.jpg" alt="Featured image of post IA aprende a jugar 2048" />&lt;p>Usé este proyecto como introducción al Aprendizaje por Refuerzo (Reinforcement Learning). Habiendo trabajado principalmente con aprendizaje supervisado y no supervisado, quería comenzar con un proyecto pequeño y sencillo para comprender rápidamente las ideas principales y crear algo divertido. Seguí este &lt;a class="link" href="https://youtu.be/L8ypSXwyBds" target="_blank" rel="noopener"
>video de YouTube&lt;/a> como referencia, el cual explica cómo usar Aprendizaje por Refuerzo (RL) para entrenar un modelo capaz de jugar al juego de la serpiente. Para hacerlo más desafiante, apliqué la misma red al juego 2048.&lt;/p>
&lt;h2 id="código">Código
&lt;/h2>&lt;p>El código tiene tres componentes principales:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>El Juego&lt;/strong>: Implementa la lógica del juego y la interfaz gráfica (GUI).&lt;/li>
&lt;li>&lt;strong>Agente&lt;/strong>: Controla la jugabilidad.&lt;/li>
&lt;li>&lt;strong>Modelo de IA&lt;/strong>: Una red neuronal que aprende a jugar y guía al agente.&lt;/li>
&lt;/ul>
&lt;h3 id="estado-del-juego">Estado del Juego
&lt;/h3>&lt;p>Modelé el estado del juego como una matriz de 4x4 que representa el tablero. Las acciones del juego están representadas por un vector con las siguientes posibilidades:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Izquierda&lt;/strong>: [1, 0, 0, 0]&lt;/li>
&lt;li>&lt;strong>Derecha&lt;/strong>: [0, 1, 0, 0]&lt;/li>
&lt;li>&lt;strong>Arriba&lt;/strong>: [0, 0, 1, 0]&lt;/li>
&lt;li>&lt;strong>Abajo&lt;/strong>: [0, 0, 0, 1]&lt;/li>
&lt;/ul>
&lt;h3 id="recompensa">Recompensa
&lt;/h3>&lt;p>El modelo de RL funciona con recompensas para cuantificar cuándo el agente actúa bien o mal. Inicialmente, definí las siguientes recompensas:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>+10 puntos&lt;/strong>: Cuando el agente duplica los puntos. Esto es crucial porque, en 2048, los puntos aumentan exponencialmente.&lt;/li>
&lt;li>&lt;strong>-10 puntos&lt;/strong>: Cuando se pierde el juego. Esto sirve como una penalización sencilla.&lt;/li>
&lt;/ul>
&lt;p>Al principio, el modelo mostraba una mejora lenta. Para solucionarlo, añadí una recompensa adicional:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>+2 puntos&lt;/strong>: Cuando se incrementan los puntos. Esta recompensa incentiva acciones que maximicen la limpieza del tablero y el progreso.&lt;/li>
&lt;/ul>
&lt;h2 id="cómo-funciona-el-modelo">Cómo Funciona el Modelo
&lt;/h2>&lt;p>El modelo es una red neuronal lineal simple. Toma el estado del juego como entrada y predice la mejor acción siguiente para maximizar la recompensa.&lt;/p>
&lt;p>Las recompensas se gestionan utilizando una técnica llamada Q-Learning. Un &lt;em>valor Q&lt;/em> representa la calidad de una decisión basada en la función de pérdida. La función de pérdida se deriva de la &lt;em>Ecuación de Bellman&lt;/em>:&lt;/p>
$$
NewQ(s, a) = Q(s, a) + \alpha [R(s, a) + \lambda \, \text{max}Q'(s', a') - Q(s, a)]
$$&lt;p>Donde:&lt;/p>
&lt;ul>
&lt;li>$Q(s, a)$: El &lt;em>valor Q&lt;/em> para un estado y acción específicos.&lt;/li>
&lt;li>$\alpha$: Tasa de aprendizaje.&lt;/li>
&lt;li>$R(s, a)$: Recompensa para un estado y acción específicos.&lt;/li>
&lt;li>$\lambda$: Tasa de descuento.&lt;/li>
&lt;li>$\text{max}Q&amp;rsquo;(s&amp;rsquo;, a&amp;rsquo;)$: Recompensa futura máxima esperada.&lt;/li>
&lt;/ul>
&lt;h2 id="experimentos-y-resultados">Experimentos y Resultados
&lt;/h2>&lt;h3 id="prueba-aleatoria-como-línea-base">Prueba Aleatoria como Línea Base
&lt;/h3>&lt;p>Para establecer una línea base, probé el puntaje promedio que se puede lograr tomando acciones aleatorias. Después de 1,000 iteraciones, el puntaje promedio fue de &lt;strong>170&lt;/strong>, muy por debajo de los 2048 puntos necesarios para ganar el juego.&lt;/p>
&lt;h3 id="resultados-iniciales">Resultados Iniciales
&lt;/h3>&lt;p>Mis primeros intentos fueron desalentadores. El modelo tenía un desempeño peor que los movimientos aleatorios. Aquí algunos resultados iniciales:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Juego 1,000&lt;/strong> | Puntaje: 208 | Récord: 416 | Puntaje Promedio: 200 | Recompensa: 640&lt;/li>
&lt;li>&lt;strong>Juego 1,000&lt;/strong> | Puntaje: 116 | Récord: 346 | Puntaje Promedio: 161 | Recompensa: 310&lt;/li>
&lt;li>&lt;strong>Juego 1,000&lt;/strong> | Puntaje: 112 | Récord: 348 | Puntaje Promedio: 146 | Recompensa: 320&lt;/li>
&lt;/ol>
&lt;p>En estos intentos, el agente desarrolló una estrategia subóptima de llenar el tablero antes de incrementar los puntos.&lt;/p>
&lt;h3 id="mejoras">Mejoras
&lt;/h3>&lt;p>Tras experimentar con los parámetros de recompensa, me centré en la fase de exploración. Inicialmente, el parámetro de &lt;em>juegos de exploración&lt;/em>, que elige movimientos aleatorios, estaba configurado en 25 juegos. Al aumentar este parámetro, el agente pudo explorar más estrategias, logrando mejores resultados:&lt;/p>
&lt;ol start="4">
&lt;li>&lt;strong>Juego 1,000&lt;/strong> | Puntaje: 478 | Récord: 478 | Puntaje Promedio: 230&lt;/li>
&lt;li>&lt;strong>Juego 1,000&lt;/strong> | Puntaje: 514 | Récord: 964 | Puntaje Promedio: 382&lt;/li>
&lt;/ol>
&lt;p>A medida que el modelo mejoraba, extendí el entrenamiento a más juegos:&lt;/p>
&lt;ol start="6">
&lt;li>&lt;strong>Juego 3,796&lt;/strong> | Puntaje: 770 | Récord: 1,366 | Puntaje Promedio: 469&lt;/li>
&lt;li>&lt;strong>Juego 4,852&lt;/strong> | Puntaje: 631 | Récord: 1,462 | Puntaje Promedio: 483&lt;/li>
&lt;/ol>
&lt;p>Finalmente, con 200 juegos de exploración y 5,000 juegos de entrenamiento, los resultados fueron los siguientes:&lt;/p>
&lt;ol start="8">
&lt;li>&lt;strong>Juego 5,000&lt;/strong> | Puntaje: 840 | Récord: 1,678 | Puntaje Promedio: 512&lt;/li>
&lt;/ol>
&lt;p>Aunque el modelo no logró ganar el juego, quedé satisfecho con el progreso. Creo que con más tiempo de entrenamiento (el último intento duró 4 horas) y capas adicionales en la red, sería posible ganar el juego con esta arquitectura.&lt;/p>
&lt;h2 id="demo">Demo
&lt;/h2>&lt;p>Aquí tienes una demostración de la aplicación, mostrando el proceso de aprendizaje del agente:&lt;/p>
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
&lt;iframe src="https://player.vimeo.com/video/1045495533" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="vimeo video" webkitallowfullscreen mozallowfullscreen allowfullscreen>&lt;/iframe>
&lt;/div>
&lt;p>Implementé atajos de teclado para controlar la velocidad del juego, ofreciendo tres opciones:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Rápida&lt;/strong>: Para un entrenamiento acelerado.&lt;/li>
&lt;li>&lt;strong>Lenta&lt;/strong>: Para observar y analizar el progreso del agente y sus errores.&lt;/li>
&lt;li>&lt;strong>Media&lt;/strong>: Casi no la utilicé.&lt;/li>
&lt;/ul>
&lt;p>El código completo para este proyecto está disponible en este &lt;a class="link" href="https://github.com/MatiasDiBernardo/RF_2048-game" target="_blank" rel="noopener"
>repositorio&lt;/a>.&lt;/p></description></item><item><title>Evaluación de diferentes modelos de Separación del Hablante</title><link>https://dibernardo.netlify.app/es/p/evaluaci%C3%B3n-de-diferentes-modelos-de-separaci%C3%B3n-del-hablante/</link><pubDate>Fri, 04 Nov 2022 00:00:00 +0000</pubDate><guid>https://dibernardo.netlify.app/es/p/evaluaci%C3%B3n-de-diferentes-modelos-de-separaci%C3%B3n-del-hablante/</guid><description>&lt;p>Este proyecto comenzó como el trabajo final para un seminario de la UNTREF llamado &lt;em>Seminario en Aplicaciones de Redes Neuronales en la recuperación de información musical&lt;/em>. El objetivo era utilizar una Red Neuronal Siamés (SNN, por sus siglas en inglés) en un contexto diferente al visto en clase (detección de similitud musical).&lt;/p>
&lt;p>Para el proyecto final de este curso, desarrollamos un modelo SNN desde cero utilizando el framework &lt;em>Keras&lt;/em> y la arquitectura &lt;em>SincNet&lt;/em> para reducir la dimensionalidad del audio, logrando buenos resultados. Más adelante, para expandir este proyecto, probé otro enfoque utilizando &lt;em>Wav2Vec&lt;/em> para la reducción de dimensionalidad y reimplementé todo el proyecto en el framework &lt;em>PyTorch&lt;/em>. Sin embargo, este intento arrojó resultados subóptimos, lo que indica que la reducción de dimensionalidad con Wav2Vec perdió información crítica necesaria para la tarea de diarización de locutores.&lt;/p>
&lt;h2 id="tarea-de-diarización-de-locutores">Tarea de Diarización de Locutores
&lt;/h2>&lt;p>El objetivo de un modelo de diarización de locutores es identificar diferentes hablantes en un flujo de audio que contiene múltiples voces. Por ejemplo, en un podcast con dos personas (A y B), el modelo debe determinar los pasos de tiempo en los que el hablante A está hablando y los pasos de tiempo en los que el hablante B está hablando (e identificar implícitamente los períodos de silencio). Estos modelos son extremadamente útiles para la edición de audio y el análisis de largas secuencias de audio con múltiples hablantes.&lt;/p>
&lt;h2 id="por-qué-redes-neuronales-siamés">¿Por qué Redes Neuronales Siamés?
&lt;/h2>&lt;p>En clase, exploramos la arquitectura siamés para comparar similitudes entre piezas musicales, desarrollando una herramienta capaz de identificar versiones de canciones famosas.&lt;/p>
&lt;p>Una Red Neuronal Siamés consiste en dos o más subredes idénticas que comparten los mismos pesos y parámetros. Está diseñada para comparar pares de entradas y medir su similitud, generalmente utilizando una métrica de distancia como la distancia euclidiana. Cada subred procesa una entrada, y las salidas se combinan para calcular un puntaje de similitud.&lt;/p>
&lt;p>Con esta comparación de similitudes en mente, quisimos aplicar estas redes a la tarea de diarización de locutores. La idea era generar embeddings de hablantes a partir de audio utilizando un modelo preentrenado y comparar las salidas de diferentes segmentos de audio. Basándonos en el puntaje de similitud, buscamos identificar los segmentos donde diferentes hablantes están hablando.&lt;/p>
&lt;h2 id="experimentos">Experimentos
&lt;/h2>&lt;p>Probé dos métodos diferentes para la extracción de características de audio que servirían como embeddings de hablantes.&lt;/p>
&lt;h3 id="implementación-en-keras-con-sincnet">Implementación en Keras con SincNet
&lt;/h3>&lt;p>En este enfoque, utilizamos la arquitectura SincNet para extraer características específicas de los hablantes a partir del audio. SincNet aplica funciones sinc aprendibles como sus filtros, que son particularmente adecuadas para el procesamiento de audio, ya que imitan los filtros de paso de banda tradicionales. Estas características se introdujeron en la Red Neuronal Siamés, que comparó pares de segmentos de audio para calcular sus puntajes de similitud. El modelo se entrenó con conjuntos de datos de audio etiquetados y observamos un rendimiento sólido al agrupar segmentos de audio por hablante, logrando límites claros entre diferentes hablantes.&lt;/p>
&lt;p>Un informe con los resultados puede encontrarse en el siguiente &lt;a class="link" href="https://github.com/MatiasDiBernardo/Speaker-Diarization-with-SNN/blob/master/TP%20Final%20Seminario%20Redes%20-%20Di%20Bernardo%20Ferreyra.ipynb" target="_blank" rel="noopener"
>notebook de Jupyter&lt;/a> (en español).&lt;/p>
&lt;h3 id="implementación-en-pytorch-con-wav2vec">Implementación en PyTorch con Wav2Vec
&lt;/h3>&lt;p>Para este método, utilicé Wav2Vec, un modelo preentrenado poderoso para la extracción de embeddings profundos de audio. A diferencia de SincNet, los embeddings de Wav2Vec se derivan del aprendizaje autosupervisado, capturando representaciones de alto nivel del audio. Estos embeddings se usaron en la Red Neuronal Siamés para comparaciones de similitud. Sin embargo, los resultados fueron subóptimos para la tarea de diarización. Parece que Wav2Vec, aunque excelente para tareas de reconocimiento de voz, perdió algunos detalles específicos del hablante necesarios para distinguir entre diferentes voces en nuestro contexto.&lt;/p>
&lt;h2 id="resultados">Resultados
&lt;/h2>&lt;p>Los experimentos demostraron que la elección del método de extracción de características es crucial para la diarización de locutores. La implementación en Keras con SincNet superó a la implementación en PyTorch con Wav2Vec, mostrando mayor precisión al identificar transiciones entre hablantes. Esto sugiere que la extracción de características específicas para la tarea, como SincNet, es más efectiva que los embeddings de propósito general como Wav2Vec para la diarización de locutores.&lt;/p>
&lt;p>El código de este proyecto está disponible en este &lt;a class="link" href="https://github.com/MatiasDiBernardo/Speaker-Diarization-with-SNN" target="_blank" rel="noopener"
>repositorio&lt;/a>.&lt;/p>
&lt;h2 id="conclusiones">Conclusiones
&lt;/h2>&lt;p>Este proyecto fue una de mis primeras experiencias con modelos de aprendizaje profundo, donde apliqué mis conocimientos a un problema sin seguir un artículo específico o utilizar un modelo preentrenado. Exploré diferentes soluciones y concluí sobre la importancia de la extracción de características y la selección del modelo.&lt;/p>
&lt;p>También me ayudó a familiarizarme con la sintaxis de los frameworks de aprendizaje profundo más populares y a solidificar mi comprensión en el proceso.&lt;/p></description></item></channel></rss>