Máster Oficial en Estadística Aplicada Departamento de Estadística e Investigación Operativa Trabajo Fin de Máster ANÁLISIS BICLUSTERING Tutor: Pedro Antonio García López Alumna: Silvia Cruz Serrano Granada, Diciembre de 2011 -2- Trabajo Fin de Máster ANÁLISIS BICLUSTERING Director del Trabajo Fin de Máster: Fdo.: Pedro Antonio García López Alumna: Fdo.: Silvia Cruz Serrano Granada, Diciembre de 2011 -3- -4- AGRADECIMIENTOS Quiero expresar mi más sincero agradecimiento a Don Pedro Antonio García López, por haberme dirigido este trabajo fin de máster. Por todas las atenciones, por el tiempo que ha perdido conmigo, y sobre todo por su apoyo tan valioso, sugerencias y confianza. Y finalmente, no puedo dejar de agradecer la comprensión de mis familiares y amigos, puesto que ellos han sido los que más me han tenido que aguantar en mis malos momentos, enfados y demás sucesos que me han acaecido a lo largo de la elaboración de este trabajo. A todos muchas gracias y un fuerte abrazo. -5- -6- ÍNDICE Capítulo I 1.1. 1.2. 1.3. Introducción al Biclustering. Definiciones y formulación del problema. Clasificación de los algoritmos de Biclustering. 9 10 12 1.3.1. Tipos de biclusters. 1.3.2. Estructuras de biclusters. 1.3.3. Técnicas de biclustering. 13 14 16 1.4. 17 Algoritmos de Biclustering. Capítulo II 2.1 . El desarrollo de “biclust”, un paquete para R. 24 2.1.1. 2.1.2. 2.1.3. 2.1.4. 2.1.5. Algoritmo BCBimax(). Algoritmo BCCC(). Algoritmo BCPlaid(). Algoritmo BCSpectral(). Algoritmo BCXmotifs(). 24 25 25 27 28 2.2. Otras funciones del paquete “biclust”. 28 Capítulo III 3.1. Aplicación práctica de Análisis Bicluster con R. 30 3.2. Yeast Data. 32 Bibliografía. 38 -7- -8- Capítulo I 1.1. Introducción al Biclustering El biclustering también conocido como co-clustering o two-mode clustering es una técnica de análisis no supervisada que permite simultáneamente la agrupación de las filas y columnas de una matriz. El término biclustering lo introdujo por primera vez Mirkin [1] (recientemente por Cheng y Church [2] en el estudio de la expresión génica), aunque la técnica la introdujo mucho antes J.A. Hartigan [3]. Esta técnica se ha aplicado mucho en los últimos años para estudiar la expresión génica, es por ello que algunos de los términos que se utilizan tienen que ver con esta disciplina. El biclustering es una evolución natural del clustering [3], que agrupa conjuntos de genes con un perfil genético similar en todas las condiciones experimentales analizadas. La capacidad analítica del biclustering para el análisis de expresión supera a la del clustering tradicional gracias principalmente a dos de sus características: agrupamiento simultáneo de genes y condiciones y solapamiento. Gracias a la primera, los grupos encontrados por un método de biclustering (biclusters) se refieren a genes que actúan de manera similar bajo sólo una serie de condiciones, no necesariamente todas, lo cual encaja con el comportamiento biológico observado (un grupo de genes pueden trabajar juntos para atender a una determinada circunstancia, pero estar desacoplados bajo otras). Mediante la segunda, podemos tener genes en más de un bicluster a la vez, lo cual es muy interesante, ya que la realidad biológica es que un gen puede tener más de una función asociada y trabajar con distintos conjuntos de genes bajo distintas condiciones. Por lo tanto, el objetivo principal de las técnicas de biclustering consiste en identificar subgrupos de genes y subgrupos de condiciones aplicando clustering sobre las filas y columnas de forma simultánea, en lugar de analizar por separado cada una de estas dimensiones. Estas ventajas teóricas se ven apoyadas por estudios prácticos, bien en los trabajos de cada autor (para recopilaciones exhaustivas de algoritmos de biclustering, consultar ([4] [5]) o en comparativas ([6] [7] [8]). Ahora bien, las técnicas de biclustering se enfrentan a una problemática similar a la de las técnicas de clustering, problemática que deriva del tipo de información que se analiza. Además, estas bases de datos contienen un gran número de atributos, del orden de miles. Por ello, el algoritmo de biclustering ha de ser robusto al ruido encontrado en los datos, además de minimizar al máximo el tiempo de ejecución. Además de estos problemas, la falta de restricciones estructurales a la hora de definir biclusters proporciona más libertad a la hora de buscar posibles soluciones. Por supuesto, este hecho tiene sus desventajas. Esta libertad provoca la posibilidad de obtener una gran cantidad de resultados, entre los que pueden existir gran cantidad de submatrices solapadas o no relevantes desde el punto de vista de la información. Así, uno de los objetivos principales de estas técnicas tiene que ser el incluir alguna medida de calidad para desestimar resultados poco interesantes. En la mayoría de los casos estas medidas son estadísticas o matemáticas y son útiles para observar la coherencia numérica de un grupo de valores. -9- La complejidad de estos problemas suele ser NP-completa. Es por ello que se ha de intentar reducir el espacio de búsqueda a la hora de encontrar las soluciones si no queremos que el tiempo de ejecución sea demasiado costoso. Aunque la mayoría de algoritmos biclustering se han ideado para analizar datos de expresión genética, estas técnicas también tienen otras aplicaciones (diagnóstico de enfermedades, fisiología celular, detectar polimorfismos y mutaciones, comportamiento de la célula ante fármacos…). 1.2. Definiciones y formulación del problema El objeto de estudio de las técnicas de biclustering será una matriz en la que cada elemento será, generalmente, un número real que representa el nivel de expresión del gen i bajo la condición experimental j. Usando la notación y definiciones que aparecen en Santamaria [9] y Rodríguez [10], dada una matriz de expresión , un bicluster es un subconjunto de genes G y condiciones C que tienen un comportamiento similar (bien los genes en G a lo largo de todas las condiciones en C, o viceversa, o ambas). Este subconjunto define una submatriz de A con los niveles de expresión de . Un algoritmo de biclustering suele encontrar varios biclusters. Para dos biclusters que se solapan, definimos la matriz de solapamiento como . Por ejemplo, los biclusters rojo y verde en la Figura 1 se solapan en las condiciones 1 y 2 y en el gen 4, pero los biclusters azul y naranja también se solapan, sólo en las condiciones 5 y 6. genes condiciones Figura 1: Ejemplo de una matriz de expresión simple, con cuatro biclusters. -10- Consideramos el caso general de una matriz A, con un conjunto de filas X y un conjunto de columnas Y, en la que los elementos corresponden a un valor que representa la relación entre la fila i y la columna j. Podemos definir la matriz A como un conjunto de filas y un conjunto de columnas . Podremos utilizar la notación para referirnos a la matriz A. Si y son subconjuntos de filas y columnas respectivamente, representa a la submatriz de A, conteniendo únicamente los elementos pertenecientes al subconjunto de filas I y al subconjunto de columnas J. Dada la matriz A, un cluster de filas es un subconjunto de filas que presentan un comportamiento similar bajo todas las columnas de la matriz. Podemos definir un cluster de filas como , donde es un subconjunto de filas . Es decir, un cluster de filas se define también como una submatriz de la matriz A. De la misma forma, un cluster de columnas se define como , donde es un subconjunto de columnas , o lo que es lo mismo, una submatriz Un bicluster de la matriz A. es un subconjunto de filas y un subconjunto de columnas donde es un subconjunto de filas y es un subconjunto de columnas . Igual que en los casos anteriores, también podemos definir al bicluster como una submatriz de la matriz A. Ahora podemos ya definir el problema específico al que se tienen que enfrentar los algoritmos de biclustering: Dada una matriz A se desea identificar un grupo de biclusters de tal manera que cada bicluster satisfaga ciertas características de homogeneidad. Las características de homogeneidad son muy variadas y de ellas depende en gran medida el algoritmo de biclustering. Aprovechando las definiciones ofrecidas, vamos a introducir una serie de notaciones que serán útiles a lo largo del estudio de los algoritmos de biclustering: Dada la matriz de datos , donde X es un conjunto de filas e Y un conjunto de columnas y un bicluster es una submatriz donde y , nos referiremos con el símbolo a la media de la fila i del bicluster. La media de la fila j del bicluster se representará por el símbolo bicluster. y será la media de todos los elementos del -11- Estos valores se definen mediante las siguientes ecuaciones: Media de la fila i del bicluster Media de la columna j del bicluster Media de todos los elementos del bicluster 1.3. Clasificación de los algoritmos de Biclustering Dado el amplio abanico de posibles técnicas a usar, es necesario hacer una clasificación de los distintos tipos de algoritmos existentes. Esta clasificación admite muchas variables por lo que únicamente nos centraremos en las más importantes. Podemos identificar los distintos aspectos que determinan un tipo de algoritmo de biclustering como: - El tipo de bicluster que se puede encontrar. A su vez, esta característica viene determinada por la función de calidad utilizada que define el tipo de homogeneidad buscada en los biclusters. - La estructura de biclusters generada. Algunos algoritmos encuentran sólo un bicluster, otros un determinado número de submatrices no solapadas y la mayoría encuentran muchos biclusters solapados entre sí. El fenómeno del solape no es algo que se tenga que desdeñar ya que en la naturaleza es posible por ejemplo que un grupo de genes sea común a distintos pathways químicos. - El tipo de técnica algorítmica utilizada. Algunas propuestas utilizan algoritmos voraces mientras que otras utilizan métodos estocásticos. - El tipo de evaluación de los resultados. He aquí uno de los aspectos más importantes y que más polémica suscita en los distintos ámbitos de la Bioinformática. Hay gran variedad de métodos de evaluación, unos más eficaces que otros. - El tipo de aplicación. El biclustering no sólo es aplicable a datos extraídos de microarrays. Esta técnica también puede ser aplicada a marketing y análisis de resultados electorales. Los tres primeros aspectos son interesantes y se comentan en los siguientes apartados. -12- 1.3.1. Tipos de biclusters Un criterio muy interesante para evaluar los distintos tipos de algoritmos de biclustering existentes tiene que ver con el tipo de bicluster que dichos algoritmos son capaces de encontrar. Las principales clases de biclusters son las siguientes, ver Figura 2: Biclusters formados por valores constantes (a). Biclusters formados por valores constantes en filas (b) o columnas (c). Biclusters formados por valores coherentes (d). Biclusters formados por valores de evolución coherente (e). a) b) c) d) e) Figura 2: Distintos tipos de biclusters. Los algoritmos de biclustering más simples identifican biclusters formados por valores constantes. Cuando el objetivo es encontrar biclusters constantes, es natural el considerar formas de reordenar filas y columnas de la matriz de datos para agrupar aquellas que sean similares. También es común el utilizar, como función de calidad, la varianza o alguna medida relacionada con ella [3]. Hay algoritmos que buscan subconjuntos de filas y subconjuntos de columnas con valores constantes en las filas o en las columnas. Un primer paso usual para identificar estos biclusters es normalizar las filas o las columnas de la matriz utilizando para ello la media de fila o de columna, respectivamente. Mediante esta práctica, este tipo de biclusters podrían transformarse en biclusters de valores constantes. En estos casos, la varianza no es suficiente para identificar de forma correcta a estos biclusters. Muchos algoritmos obtienen resultados de este tipo [11] [12] [13] [14]. El tercer tipo hace referencia a biclusters con valores coherentes tanto en filas como en columnas. Este tipo de biclusters no se pueden encontrar simplemente considerando que los valores en el bicluster se obtienen a partir de un modelo aditivo o multiplicativo. Se requieren métodos más sofisticados en lo que se utiliza el análisis de la varianza entre grupos y una forma de co-varianza entre filas y columnas del bicluster para evaluar la calidad de los resultados. Muchos de los algoritmos más interesantes son capaces de obtener biclusters como los descritos anteriormente [2] [14] [15] [16] [17] [18] [19]. -13- Por último hemos de citar a los biclusters basados en una evolución coherente de sus valores. Algunos algoritmos de biclustering intentan solucionar el problema de encontrar evoluciones coherentes a lo largo de las filas o columnas de una matriz sin tener en cuenta sus valores exactos. Esta forma totalmente distinta de considerar a un bicluster se tiene en cuenta en importantes algoritmos [20] [21] [22]. 1.3.2. Estructuras de biclusters Los algoritmos de biclustering pueden plantearse dos tipos distintos de objetivos: encontrar un solo bicluster, tal y como aparece en la Figura 3(a) o encontrar K biclusters, siendo K un número conocido o no de antemano. La mayoría de técnicas de biclustering asumen la existencia de varios biclusters en la matriz de datos [3] [2] [9] [19] [12] [18] [22] [23] [17] [16] aunque otras sólo intentan encontrar uno. Estas últimas, aunque tienen la capacidad de poder localizar más de un resultado, siempre se centran en aquel que siga un determinado criterio [20]. Cuando los algoritmos asumen que existe más de un bicluster en la matriz de datos, como resultado se pueden obtener varios tipos de estructuras, ver Figura 3: Biclusters con filas y columnas exclusivas (bloques diagonales de forma rectangular obtenidos tras una reordenación de filas y columnas) (b). Biclusters sin solape con estructura de tablero de ajedrez (c). Biclusters con filas exclusivas (d). Biclusters con columnas exclusivas (e). Biclusters no solapados con estructura de árbol (f). Biclusters no solapados y no exclusivos (g). Biclusters solapados con estructura jerárquica (h). Biclusters arbitrarios (i). a) b) f) c) g) d) h) Figura 3: Posibles estructuras de biclusters. -14- e) i) Dependiendo de la técnica a utilizar se podrá obtener un tipo u otro de estructura. Hay métodos que forman una imagen coloreada de la matriz A, en la que cada elemento tiene un tono de color asociado a su nivel de expresión. Posteriormente, se reordenan filas y columnas de tal forma que se va formando una imagen con bloques de datos del mismo color. Estos bloques son un subconjunto de filas y columnas con valores similares de expresión, es decir, biclusters. Una reordenación ideal de la matriz A producirá una imagen con cierto número K de bloques diagonales, tal y como aparece en la Figura 3(b). Esta situación ideal corresponde a la existencia de K bloques exclusivos y exhaustivos, es decir, cada fila y cada columna de la matriz corresponde exclusivamente a uno de estos biclusters. Aunque ha quedado demostrado que este reordenamiento ideal rara vez se da en la naturaleza [19]. Así pues, la siguiente consideración a la hora de detectar biclusters sería partir del hecho de que filas y columnas pueden pertenecer a más de un bicluster y asumir una estructura de tablero de ajedrez en los datos, Figura 3(c). De esta forma, aceptamos la existencia de K biclusters no exclusivos y no solapados. Algunas técnicas asumen esta estructura [17]. Otros métodos asumen que las filas sólo pueden pertenecer a un bicluster, mientras que las columnas pueden pertenecer a varios biclusters. Esta estructura, Figura 3(d), es usada por Tang et al. [18]. Sin embargo, estos algoritmos también pueden obtener biclusters con columnas exclusivas simplemente cambiando la orientación de la matriz de datos, Figura 3(e). Las estructuras presentadas en la Figura 3 de la (b) a la (e), asumen que los biclusters son exhaustivos, es decir, cada fila y cada columna pertenecen al menos a un bicluster. Sin embargo podemos considerar variaciones no exhaustivas de estas estructuras para hacer posible que alguna fila o columna se quede sin pertenecer a ninguna submatriz resultante [3] [16]. Un inconveniente de este tipo de aproximaciones es que ninguna de ellas acepta el solape. Las estructuras anteriores son restrictivas en muchos aspectos. Por un lado, algunas de ellas asumen que, por motivos de visualización, todos los biclusters identificados deberían poder observarse directamente en la matriz de datos después de realizar un reordenamiento de filas y columnas. Por otro lado está también la exhaustividad. Sin embargo, en los datos reales es más común que no existan restricciones, es decir, que alguna fila o columna no participe en el resultado final y que los biclusters se solapen. Aún así, es posible habilitar estas dos propiedades, sin eliminar las propiedades de visualización, si se adopta la estructura jerárquica propuesta por Hartigan [3], ver Figura 3(h). Esta estructura tiene el inconveniente de que los biclusters son disjuntos o tienen que incluirse los unos a los otros. Podemos encontrar dos especializaciones de esta estructura en la Figura 3(f) y en la Figura 3(c). -15- Finalmente, la última de las estructuras Figura 3(i), representa el caso más general y con menos restricciones. Esta es la estructura más buscada por la mayoría de los algoritmos de biclustering. Se podría decir que es algo caótica, al permitir todo tipo de fenómenos: exhaustividad, no exhaustividad, solape, no solape, etc. Pero en principio es la más próxima a la realidad. 1.3.3. Técnicas de biclustering El grueso de algoritmos de biclustering se ha desarrollado desde el año 2000. Hay técnicas muy variadas que han resultado ser de gran efectividad. Y todas ellas tienen características comunes y diferencias que la hacen únicas. Hay algunos métodos que se dedican a detectar un sólo bicluster en cada ejecución. Por ejemplo, en la propuesta realizada por Cheng y Church [2] se identifica un bicluster cada vez, se sustituye dicha submatriz por valores aleatorios en la matriz original y se comienza de nuevo el proceso para encontrar nuevos biclusters. Lazzeroni y Owen [19] también detectan un solo bicluster, al igual que Ben-Dor et al. [20]. Otros métodos tienen como objetivo descubrir un conjunto de biclusters, siendo el número de elementos de dicho conjunto desconocido a priori o establecido de forma fija para una determinada ejecución. Hartigan [3] genera un par de biclusters a la vez dividiendo cada bicluster descubierto en dos trozos en cada iteración. El método basado en aplicar de forma conjunta técnicas de clustering sobre filas y columnas, Coupled Two-Way Clustering (CTWC) [11], utiliza un algoritmo de clustering jerárquico que genera clusters estables de filas y columnas en cada iteración y, consecuentemente, produce un conjunto de biclusters de forma simultánea. Mientras que existen métodos como los anteriores que van descubriendo un grupo de biclusters y cuyo número va en aumento a lo largo de un proceso iterativo, hay otras técnicas que generan un conjunto de biclusters de una sola vez. Tal es el caso del algoritmo FLOC (Flexible Overlapped biClustering) [14] [15], que genera un conjunto inicial de biclusters y va mejorando la calidad de los mismos mediante modificaciones de forma iterativa. Debido a la gran variedad de técnicas propuestas es necesario hacer una clasificación para que podamos comentar los algoritmos de biclustering que han tenido mayor repercusión durante los últimos años. Esta clasificación está basada en el tipo de método utilizado para encontrar submatrices en una matriz de datos: Divide y vencerás. Combinación de clustering sobre filas y columnas. Búsqueda voraz iterativa. Búsqueda exhaustiva. Identificación de parámetros de distribución. Búsqueda estocástica. -16- 1.4 . Algoritmos de Biclustering Este apartado vamos a dedicarlo a la descripción del primer algoritmo, propiamente dicho, de biclustering, el algoritmo de Cheng y Church, se trata de una técnica de búsqueda voraz iterativa. Cheng y Church Cheng y Church [2] establecieron un método que basaba la búsqueda del resultado final en un problema de optimización. Parten de la suposición de para que un subgrupo sea un bicluster, sus valores han de evolucionar al unísono, y esta característica estaba representada por un valor estadístico: Mean Squared Residue (MSR). Para llegar a entender el trabajo de Cheng y Church es necesario conocer a fondo esta medida. Sea un bicluster. El residuo R de un elemento del bicluster es: Donde: es la media de la fila i-ésima del bicluster. es la media de la columna j-ésima del bicluster. es la media de todos los elementos del bicluster. El MSR de un bicluster se define como: Este valor se considera como un índice de calidad. El MSR es la varianza del conjunto de todos los valores del bicluster, más la varianza de la fila y varianza de columna. Es por ello que dicho valor mide el nivel de coherencia de los valores a lo largo de las filas y las columnas. A mayor valor del MSR, menos calidad tendrá el bicluster. Este valor global nos indica cómo se interrelacionan los datos de la matriz, es decir, si existe alguna coherencia en la evolución de sus valores o son aleatorios. - Un valor alto de H significa que los datos no están correlacionados. - Un valor bajo de H implica que la matriz está correlacionada. - Si significaría que los datos de la matriz fluctúan al unísono. -17- Veamos lo anterior con un ejemplo: Sea la matriz de datos A: Donde: -18- Calculamos: Calculamos ahora: Como , los datos de la matriz fluctúan al unísono. Cheng y Church. Algoritmo. Partiendo de esta definición, los autores definieron al subconjunto de filas y columnas valor umbral: como aquel cuyo valor de residuo no supera un determinado . Por consiguiente, el objetivo principal del primer algoritmo de biclustering, propiamente dicho, es el de obtener una submatriz del mayor tamaño posible y con un residuo no superior a un determinado umbral. Cheng y Church explican en su trabajo, haciendo uso de la teoría de grafos, que la búsqueda de un bicluster máximo se puede asemejar a la búsqueda de un subgrafo máximo en un grafo bipartito. Y dicho problema tiene una complejidad NP-completa [24]. Por ello, plantean un algoritmo voraz para converger de forma rápida a una submatriz máxima local que sea menor que un residuo dado, no teniendo que ser ésta la mejor solución posible. -19- El algoritmo de Cheng y Church se entiende como un algoritmo de búsqueda local. Se muestra a continuación: Cheng-Church (U, V, A, ) Define Define Define Define Define Inicializar a bicluster con Primera fase: Mientras hacer Calcula para Calcula para Si asignar En otro caso Segunda fase: Asignar Mientras hacer Asignar Calcula para Calcula para Si asignar En otro caso Muestra -20- Este algoritmo toma como entrada a la matriz original de datos y un valor umbral de residuo. Su objetivo es encontrar un solo bicluster en cada ejecución y para ello lleva a cabo dos fases principales. En la primera fase, el algoritmo elimina filas y columnas de la matriz original. En cada paso, en el que la submatriz en construcción consta de I filas y J columnas, el algoritmo estudia el conjunto posible de movimientos. Para cada fila se calcula el valor de su residuo, , y lo mismo para cada columna, . El siguiente paso es seleccionar la fila o columna con mayor valor de residuo y eliminarla de la submatriz. El proceso finaliza cuando el residuo de la submatriz sea . Para implementar este borrado masivo, los autores se basan en la teoría de que aquellas filas o columnas con un alto valor de residuo pueden ser eliminadas con la garantía de una mejora en el residuo total de la submatriz resultante. En la segunda fase del algoritmo, filas y columnas se añaden a la submatriz resultante de la fase anterior. Para ello se sigue un esquema similar al anterior, pero esta vez buscando las filas y las columnas de la matriz original con menores valores de residuo. El proceso finaliza cuando un posible aumento del tamaño de la submatriz hace que el valor de su residuo MSR cruce el umbral fijado en los parámetros de entrada. Así pues, el resultado final es la submatriz máxima que cumple la condición de no sobrepasar el valor umbral del MSR. Con respecto al pre-procesamiento de los datos, los autores sustituyen los huecos en la matriz de entrada a partir de valores aleatorios. La propuesta de Cheng y Church ha sido de gran relevancia al ser la primera que introducía el concepto de bicluster y que usaba un algoritmo original para su obtención. Sin embargo, el algoritmo propuesto tiene múltiples lagunas que a continuación vamos a comentar. No obstante, ha sido fuente de múltiples estudios y muchos trabajos se han generado con el objetivo de mejorar sus debilidades. En primer lugar, el algoritmo tiene como objetivo en cada ejecución encontrar un solo bicluster. Sin embargo, los autores ofrecen la posibilidad de encontrar un número determinado K de biclusters siguiendo un método más discutible: cada vez que una submatriz se genera, se sustituye en la matriz original por una serie de números aleatorios, generados a partir de un rango de valores que han de ser introducidos por el usuario y vuelta a empezar. Esta modificación de la matriz original desvirtúa totalmente la naturaleza de los datos, confiriendo a los resultados finales dudosa credibilidad. En segundo lugar, tenemos el problema del umbral. En los experimentos llevados a cabo por los autores se fija un valor de umbral igual a 300. La justificación de este valor nada tiene que ver con fijar una calidad determinada, sino con hacer interesante el experimento. El valor máximo del MSR supone una limitación desde el punto de vista de que cada base de datos debería contar con un valor aproximado que determinara la calidad de los -21- biclusters deseados, algo que es verdaderamente complicado. A pesar de ello, este valor lo han utilizado multitud de investigadores en sus técnicas para establecer comparaciones de resultados. Aún así, un trabajo reciente [25] ha demostrado que el MSR no es una medida de calidad adecuada. El trabajo de Aguilar presenta una serie de fenómenos que son muy frecuentes entre los biclusters y que pueden influir directamente en la evaluación final de los mismos. En el siguiente capítulo vamos a describir el desarrollo de “biclust”, un paquete para R con la implementación de varios algoritmos de biclustering. -22- -23- Capítulo II 2.1. El desarrollo de “biclust”, un paquete para R El paquete “biclust” de R ofrece varios algoritmos para encontrar biclusters en dos dimensiones: Bimax, Cheng and Church, Plaid Model, Spectral y Xmotifs. Además, el paquete proporciona los métodos de procesamiento de datos (normalización y discretización), visualización y validación de las soluciones bicluster. 2.1.1. Algoritmo BCBimax () Descripción: Este algoritmo está basado en el trabajo de Prelic et. al.(2006) [6]. Busca submatrices de unos en una matriz lógica. Utiliza el código original de C de los autores. El algoritmo lleva a cabo los siguientes pasos: - Reorganiza las filas y las columnas para concentrar los unos en la parte superior derecha de la matriz. - Divide la matriz en dos submatrices. Cada vez que en una de las submatrices se encuentran sólo unos, esta submatriz se devuelve. Con el fin de obtener resultados satisfactorios el método tiene que ser reiniciado varias veces con diferentes puntos de partida. Aunque el algoritmo fue originalmente diseñado para ofrecer ideas de validación de bicluster, también se puede utilizar como un método bicluster. Sintaxis: biclust(x, method=BCBimax(), minr=2, minc=2, number=100) biclust(x, method=BCrepBimax(), minr=2, minc=2, number=100, maxc=12) Argumentos: x: matriz lógica que representa los datos. method: BCBimax, para llevar a cabo el algoritmo Bimax. minr: tamaño mínimo de fila del bicluster resultante. minc: tamaño mínimo de columna del bicluster resultante. number: número de bicluster que se encuentran. maxc: tamaño máximo de columna del bicluster resultante. -24- 2.1.2. Algoritmo BCCC () Descripción: Este algoritmo está basado en el trabajo de Cheng y Church (2000) [2]. Busca submatrices con una puntuación inferior a un umbral específico en la matriz de datos estandarizados. El algoritmo lleva a cabo los siguientes pasos: - Elimina filas y columnas con una puntuación mayor que alpha. - Elimina filas y columnas con la mayor puntuación. - Agrega filas o columnas hasta que se alcance el nivel alpha. Sintaxis: biclust(x, method=BCCC(), delta = 1.0, alpha=1.5, number=100) Argumentos: x: matriz de datos. method: BCCC, para llevar a cabo el algoritmo CC. delta: máximo de puntuación aceptada. alpha: factor de escala. number: número de bicluster que se encuentran. 2.1.3. Algoritmo BCPlaid () Descripción: Este algoritmo está basado en el trabajo de Turner et al., (2003) [26]. Se trata de una mejora de “Plaid Models for Gene Expression Data” (Lazzeroni and Owen, 2000) [19]. El modelo se ajusta a los datos a través de la minimización del error. El algoritmo original era adecuado a las k capas para el modelo: usando mínimos cuadrados ordinarios (OLS), donde: representan la media, la fila y los efectos de la columna y o una columna es miembro de la capa, respectivamente. -25- y k identifican si una fila Sintaxis: biclust(x, method=BCPlaid(), cluster="b", fit.model = y ~ m + a + b, background = TRUE, background.layer = NA, background.df = 1, row.release = 0.7, col.release = 0.7, shuffle = 3, back.fit = 0, max.layers = 20, iter.startup = 5, iter.layer = 10, verbose = TRUE) Argumentos: x: matriz de datos en la que se van a encontrar a los bicluster. method: BCPlaid, para llevar a cabo el algoritmo Plaid. cluster: ’r’, ’c’ or ’b’, para las filas del cluster, columnas o ambas (por defecto ’b’). fit.model: modelo para adaptarse a cada capa. Por lo general, se usa un modelo lineal que estima tres parámetros: m (constante para todos los elementos en el bicluster), a (constante para todas las filas en el bicluster) y b (constante para todas las columnas). Por lo tanto, por defecto: y ~ m + a + b. background: si es TRUE=Verdadero, el método tendrá en cuenta una capa de fondo (constante para todas las filas y columnas) que está presente en la matriz de datos. background.layer: si es TRUE=Verdadero se puede especificar una capa de fondo propia (con la dimensión de la matriz x). background.df: grados de libertad de la capa de background.layer si se especifica. shuffle: antes de que la capa se añada, su significación estadística se compara con el número de capa que se obtiene de forma aleatoria definido por este parámetro. Por defecto es 3, el número más alto que podría afectar al rendimiento del equipo. iter.startup: número de iteraciones para encontrar los valores de partida. iter.layer: número de iteraciones para encontrar cada capa. back.fit: después de que se añada una capa, las iteraciones adicionales se pueden hacer para perfeccionar la instalación de la capa (establecido por defecto a 0). row.release: número escalar comprendido entre [0,1] (con intervalo recomendado [0.50.7] usado como umbral para podar filas en las capas dependiendo de la homogeneidad en las filas. col.release: como el anterior, pero con columnas. max.layers: número máximo de capas para incluir en el modelo. verbose: si es TRUE=Verdadero, muestra información adicional sobre los progresos. -26- 2.1.4. Algoritmo BCSpectral () Descripción: Este algoritmo está basado en el trabajo de Kluger et al. (2003) [17]. El algoritmo supone que los datos de microarrays normalizados tienen una estructura de tablero de ajedrez que se pueden descubrir por el uso de vectores propios de la descomposición de la matriz en sus valores singulares (SVD), aplicada a los genes (filas) y a las condiciones (columnas). El algoritmo lleva a cabo los siguientes pasos: - Reordenar la matriz de datos y elegir el método de normalización. - Calcular la descomposición de la matriz en sus valores singulares para obtener los valores y vectores propios. - Dependiendo de los métodos de normalización elegidos, construir biclusters empezando por el valor propio más grande o el segundo más grande. La cantidad de bicluster depende del número y del valor de los valores propios. Sintaxis: biclust(x, method=BCSpectral(), normalization="log", numberOfEigenvalues=3, minr=2, minc=2, withinVar=1) Argumentos: x: matriz de datos en la que se van a encontrar a los bicluster. method: BCSpectral, para llevar a cabo el algoritmo Spectral. normalization: se permiten tres métodos como los descritos por Kluger et al.: "log" (Normalización Logarítmica), “irrc” (Reescalado independiente de filas y columnas) y "bistochastization". Si se usa la normalización “log” hay que asegurarse que se puede aplicar logaritmo a los elementos de la matriz de datos, si hay valores inferiores a 1, automáticamente se hará 1+abs(min(mat)). Por defecto es “log” la recomendada por Kluger et al. numberOfEigenvalues: número de valores propios considerados para encontrar bicluster. Cada fila (gen) de vectores propios se combinará con todas las columnas (condiciones) de vectores propios. Hay que tener en cuenta el elevado número que podría aumentar drásticamente el rendimiento del equipo. Por lo general, se utilizan sólo los primeros vectores propios. Con los métodos “irrc” y "bistochastization", el primer valor propio contiene información irrelevante, por lo que se ignora. minr: número mínimo de bicluster que deben tener las filas. El algoritmo no considerará los bicluster más pequeños. minc: número mínimo de bicluster que deben tener las columnas. El algoritmo no considerará los bicluster más pequeños. withinVar: variación máxima permitida. -27- 2.1.5. Algoritmo BCXmotifs () Descripción: Este algoritmo está basado en el trabajo de Murali and Kasif (2003) [27]. Sintaxis: biclust(x, method=BCXmotifs(), ns=10, nd=10, sd=5, alpha=0.05, number=100) Argumentos: x: matriz de datos. method: BCXmotifs, para llevar a cabo el algoritmo motifs. ns: número de filas elegidas. nd: número de repeticiones. sd: tamaño de la muestra en las repeticiones. alpha: factor de escala para la columna de resultados. number: número de bicluster que se encuentran. 2.2. Otras funciones del paquete “biclust” Además de los algoritmos descritos anteriormente, nuestro paquete proporciona varios métodos de preprocesamiento de datos. Otras funciones proporcionan utilidades para la validación de cluster, como es la adaptación del conocido índice Jaccard para la comparación de dos cluster (jaccardind()). La función constantVariance() implementa el índice de variación de Madeira y Oliveira (2004). Otro aspecto importante del paquete es la visualización de los resultados bicluster. Parallelcoordinates (función parallelCoordinates()) se pude utilizar para visualizar la similitud de las filas sobre las columnas dentro de un bicluster. Heatmaps (drawHeatmap()) pone de relieve la diferencia entre el bicluster y los alrededores de filas y columnas. El bubbleplot (Bubbleplot()) de Santamaria et al. (2007) representa bicluster de dos dimensiones. Cada burbuja representa un bicluster, su posición determinada por los genes y condiciones que agrupa. El color representa el tipo de biclustering y el tamaño indica la dimensión de la submatriz que abarca el bicluster. -28- -29- Capítulo III 3.1. Aplicación práctica de Análisis Bicluster con R Para facilitar la comprensión de los algoritmos vistos en el Capítulo II, se presentan algunos ejemplos, que incorporan las rutinas del paquete biclust de R, a los que vamos a aplicar dichos algoritmos. A continuación, mostramos los resultados: Algoritmo BCBimax () test <- matrix(rnorm(5000), 100, 50) test[11:20,11:20] <- rnorm(100, 3, 0.1) loma <- binarize(test,2) res <- biclust(x=loma, method=BCBimax(), minr=4, minc=4, number=10) res Resultado: An object of class Biclust call: biclust(x = loma, method = BCBimax(), minr = 4, minc = 4, number = 10) Sólo se ha encontrado un bicluster con 10 filas y 10 columnas. Algoritmo BCCC () test <- matrix(rbinom(400, 50, 0.4), 20, 20) res <- biclust(test, method=BCCC(), delta=1.5, alpha=1, number=10) res Resultado: An object of class Biclust call: biclust(x = test, method = BCCC(), delta = 1.5, alpha = 1, number = 10) Se han encontrado cuatro bicluster: BC 1 BC 2 BC 3 BC 4 Número de filas: 6 6 5 3 Número de columnas: 5 6 6 5 El primer bicluster tiene 6 filas y 5 columnas, el segundo bicluster está formado por 6 filas y 6 columnas, el tercero por 5 filas y 6 columnas y el cuarto bicluster por 3 filas y 5 columnas. -30- Algoritmo BCPlaid () #microarray matrix data(BicatYeast) res<-biclust(BicatYeast, method=BCPlaid(), verbose=FALSE) res Resultado: An object of class Biclust call: biclust(x = BicatYeast, method = BCPlaid(), verbose = FALSE) Se han encontrado cinco bicluster: BC 1 BC 2 BC 3 BC 4 BC 5 Número de filas: 48 135 44 8 85 Número de columnas: 5 6 6 2 2 El primer bicluster tiene 48 filas y 5 columnas, el segundo bicluster está formado por 135 filas y 6 columnas, el tercero por 44 filas y 6 columnas, el cuarto bicluster por 8 filas y 2 columnas y finalmente el quinto contiene 85 filas y 2 columnas. Algoritmo BCSpectral () test <- matrix(rnorm(5000),100,50) test[11:20,11:20] <- rnorm(100,10,0.1) res1 <- biclust(test, method=BCSpectral(), numberOfEigenvalues=1) res1 Resultado: An object of class Biclust call: biclust(x = test, method = BCSpectral(), numberOfEigenvalues = 1) Se han encontrado cinco bicluster: BC 1 BC 2 BC 3 BC 4 BC 5 Número de filas: 10 10 3 3 3 Número de columnas: 6 4 17 6 23 El primer bicluster tiene 10 filas y 6 columnas, el segundo bicluster está formado por 10 filas y 4 columnas, el tercero por 3 filas y 17 columnas, el cuarto bicluster por 3 filas y 6 columnas y finalmente el quinto contiene 3 filas y 23 columnas. -31- Algoritmo BCXmotifs () data(BicatYeast) x<-discretize(BicatYeast) res <- biclust(x, method=BCXmotifs(), ns=20, nd=20, sd=5, alpha=0.01, number=10) res Resultado: An object of class Biclust call: biclust(x = x, method = BCXmotifs(), ns = 20, nd = 20, sd = 5, alpha = 0.01, number = 10) Se han encontrado diez bicluster, R nos muestra los cinco primeros: Número de filas: Número de columnas: BC 1 BC 2 BC 3 BC 4 BC 5 233 53 37 12 10 6 7 7 12 13 El primer bicluster tiene 233 filas y 6 columnas, el segundo bicluster está formado por 53 filas y 7 columnas, el tercero por 37 filas y 7 columnas, el cuarto bicluster por 12 filas y 12 columnas y el quinto contiene 10 filas y 13 columnas. 3.2. Yeast Data Para seguir ilustrando la funcionalidad del paquete biclust, en la siguiente sección se muestra un conjunto de datos llamado BicatYeast que incluye dicho paquete y sobre el cual aplicaremos la técnica bicluster. Prelic et al. (2006) utilizan esta base de datos para mostrar su técnica de bicluster. En primer lugar cargamos los datos: > library(biclust) > data(BicatYeast) Ilustramos (en unas líneas) el conjunto de datos: 262603_at -0.383883700 0.660195300 -0.041766547 -0.186557520 -0.055341594 -0.214601670 -1.052989000 253161_at 0.277210800 0.186483280 -0.258689430 -1.616643000 -0.706773200 -0.545801500 -0.684479650 252415_at -0.249895440 -0.897594300 -0.279498300 -0.561008930 -0.884164000 -0.116289860 -0.557930230 ……………………………………………………………………………………………. 258436_at -0.971316200 1.193447400 -0.719946560 262887_at -0.088410250 -0.360049700 0.096557856 -0.832817260 0.050989740 -0.242015760 -0.242423500 -0.014255229 -0.046032485 0.020413702 0.029053356 ……………………………………………………………………………………………. -32- A continuación, se lleva a cabo el preprocesamiento de los datos, pues los datos reales tienden a tener ruido, ser incompletos e inconsistentes. Las tareas y técnicas de preprocesamiento de datos pueden mejorar la calidad de los datos, ayudando a mejorar la precisión y eficiencia de los procesos de análisis de datos, de ahí que el preprocesamiento de datos se convierta en un paso preliminar importante. > xmotifdata<-discretize(BicatYeast, nof=10, quant=TRUE) Los datos que se obtienen son los siguientes: 251342_at 4 6 2 2 3 3 259502_at 5 5 2 1 4 5 264467_at 6 3 1 2 3 2 257216_at 4 6 2 1 4 5 255872_at 6 4 7 6 7 6 …………………………………………………………………………………. 258436_at 5 6 6 4 4 3 262887_at 5 6 1 1 6 3 …………………………………………………………………………………. > bimaxdata<-binarize(abs(BicatYeast), threshold=2) Los datos que se obtienen son los siguientes: 258377_at 0 0 0 0 0 0 249743_at 0 0 0 0 0 0 256177_at 0 0 0 0 0 0 247691_at 0 0 0 0 0 0 262148_at 0 0 0 0 0 0 …………………………………………………………………………………. 258436_at 262887_at 0 0 0 0 0 0 0 0 0 0 0 0 …………………………………………………………………………………. Después calculamos todos los resultados de los diferentes bicluster: >Bicatresplaid<-biclust(x = BicatYeast, method = BCPlaid(), back.fit = 2, shuffle = 2, fit.model = ~ m + a + b, iter.startup = 5, iter.layer = 30, verbose = F) > Bicatresxmotif<-biclust(x = xmotifdata, method = BCXmotifs(), ns = 200, nd = 200, sd = 4, alpha = 0.05, number = 50) > Bicatrescc <- biclust(x = BicatYeast, method = BCCC(), delta = 0.01, number = 50) > Bicatresspect <- biclust(x = BicatYeast, method = BCSpectral(), withinVar = 4) > Bicatresbi <- biclust(x = bimaxdata, method = BCBimax(), minr = 5, minc = 5, number = 50) -33- Según el algoritmo que utilicemos obtendremos diferentes resultados, por ejemplo: > Bicatresxmotif An object of class Biclust call: biclust(x = xmotifdata, method = BCXmotifs(), ns = 200, nd = 200, sd = 4, alpha = 0.05, number = 50) Number of Clusters found: 38 First 5 Cluster sizes: Number of Rows: Number of Columns: BC1 BC2 BC3 BC4 BC5 23 15 14 20 10 5 6 5 5 5 Contiene muchos bicluster con igual número de columnas. Mientras que el algoritmo BCPlaid(): > Bicatresplaid An object of class Biclust call: biclust(x = BicatYeast, method = BCPlaid(), back.fit = 2,shuffle = 3, fit.model = ~m + a + b,iter.startup = 5, iter.layer = 30, verbose = F) Number of Clusters found: 7 First 5 Cluster sizes: Number of Rows: Number of Columns: BC1 23 12 BC2 28 5 BC3 26 7 BC4 24 3 BC5 3 3 Contiene pocos bicluster con igual número de columnas. Una primera validación se puede hacer comparando simplemente el índice de Jaccard de los 5 resultados. Obtenemos para ello la siguiente matriz: > jacresult[1, 2] <- jaccardind(Bicatresplaid, Bicatresxmotif) NOTA: se hace con todas la posibles combinaciones. > jacresult -34- ALGORITMOS ALGORITMOS BCPlaid BCXmotifs BCCC BCSpectral BCBimax BCPlaid 1.0000000 0.0128998 0.0044838 0.0069520 0.0000000 BCXmotifs 0.0128998 1.0000000 0.0321175 0.0042682 0.0060214 BCCC 0.0044838 0.0321175 1.0000000 0.0116795 0.0000000 BCSpectral 0.0069520 0.0042682 0.0116795 1.0000000 0.0000000 BCBimax 0.0000000 0.0060214 0.0000000 0.0000000 1.0000000 El índice de Jaccard de los diferentes algoritmos de bicluster es cercano a cero lo que indica que los bicluster son completamente diferentes los unos de los otros. > drawHeatmap(x = BicatYeast, bicResult, number = 1, local = F) Figura 4: Heatmap del primer bicluster de los algoritmos CC, Xmotifs y Plaid. -35- La Figura 4 corresponde a un heatmap, es una representación en dos dimensiones de la matriz, donde las filas representan genes y la columnas condiciones. Cada nivel de expresión se representa como un cuadrado de color en la posición correspondiente a su gen y su condición. Las filas y columnas se han reordenado para mostrar un bicluster con media expresión en la esquina superior izquierda, delimitado por las líneas amarillas. Es importante destacar que el color depende del nivel de expresión y suele seguir una escala bicolor o tricolor; en nuestro caso el verde nos indica baja expresión, el negro expresión media y el rojo alta expresión. A continuación, hacemos una segunda validación calculando constantVariance, si llevamos a cabo: > varresult <- constantVariance(x = BicatYeast, resultSet = Bicatrescc, number = 1) Para el primer bicluster en cada resultado obtenemos: > varresult BCPlaid 1.06805 BCXmotifs 0.59070 BCCC 0.58055 BCSpectral 1.68799 BCBimax 2.44496 Los cálculos muestran el resultado esperado. BCCC busca bicluster constantes y BCXmotifs contiene genes en igual estado. -36- -37- Bibliografía. [1] B. Mirkin (1996). Mathematical Classification and Clustering. Kluwer Academic Publishers. [2] Y. Cheng and G.M. Church (2000). Biclustering of expression data. Proceedings of the 8th International Conference on Intelligent Systems for Molecular Biology: 93–103. [3] J.A. Hartigan (1972). Direct clustering of a data matrix. Journal of the American Statistical Association (American Statistical Association) 67 (337): 123–9. [4] A. Tanay, R. Sharan, and R. Shamir (2002). Discovering statistically significant biclusters in gene expression data. Bioinformatics, 18:S136–S144. [5] S. Madeira and A. Oliveira (2004). Biclustering algorithms for biological data analysis: a survey. IEEE/ACM Transactions of Computational Biology and Bioinformatics, 1(1):24–45. [6] A. Prelic, S. Bleuer, P. Zimmermann, A. Wille, P. Bühlmann, et al. (2006) A systematic comparison and evaluation of biclustering methods for gene expression data. Bioinformatics, 22(9):1122–1129. [7] D. J. Reiss, N. S. Baliga, and R. Bonneau (2006). Integrated biclustering of heterogeneous genome-wide datasets for the inference of global regulatory networks. BMC Bioinformatics,1:662–671. [8] Y. Okada, W. Fujibuchi, and P. Horton (2007). A biclustering method for gene expression module discovery using a closed itemset enumeration algorithm. IPSJ Digital Courier, 3:183–192. [9] R. Santamaria (2009). Análisis Visual de Datos de Expresion Génica Mediante Biclustering. Tesis Doctoral. Universidad de Salamanca. [10] D. Savio Rodríguez (2006). Análisis de datos de expresión genética mediante técnicas de biclustering. [11] G. Getz, E. Levine, and E. Domany (2000). Coupled two-way clustering analysis of gene microarray data. Proceedings of the NaturalAcademy of Sciences USA, pages 12079– 12084. [12] E. Segal, B. Taskar, A. Gasch, N. Friedman, and D. Koller (2001). Rich probabilistic models for gene expression. Bioinformatics, 17:243–252. [13] E. Segal, H. Wang, and D. Koller (2003). Discovering molecular pathways from protein interaction and gene expression data. Bioinformatics, 19:264–272. [14] J. Yang and W. Wang (2002). Improving performance of bicluster discovery in a large data set. 6th ACM International Conference on Research in Computational Molecular Biology. [15] J. Yang and W. Wang (2003). Enhanced biclustering on expression data. 3rd IEEE Conference on Bioinformatics and Bioengineering, pages 321–327. [16] H. Wang, W. Wang, J. Yang, and P. S. Yu (2002). Clustering by pattern similarity in large data sets. Proceedings ACM SIGMOD International Conference on Management of Data, pages 394–405. -38- [17] Y. Kluger, R. Basri, J. Chang, and M. Gerstein (2003). Spectral biclustering of microarray data: coclustering genes and conditions. Genome Research, 13:703–716. [18] C. Tang, A. Zhang, L.and Zhang, and M. Ramanathan (2001). Interrelated two-way clustering: An unsupervised approach for gene expression data analysis. Proceeding of BIBE2001: 2nd IEEE International Symposium on Bioinformatics and Bioengineering, pages 41–48. [19] L. Lazzeroni and A. Owen (2000). Plaid models for gene expression data. Technical report, Stanford University. [20] A. Ben-Dor, B. Chor, R. Karp, and Z. Yakhini (2002). Discovering local structure in gene expression data: The order–preserving submatrix problem. Proceedings of the 6th International Conference on Computacional Biology (RECOMB’02), pages 49–57. [21] J. Liu and W. Wang (2003). Op-cluster: Clustering by tendency in high dimensional space. Proceedings of the 3rd IEEE International Conference on Data Mining, pages 187– 194. [22] A. Tanay, R. Sharan, and R. Shamir (2002). Discovering statistically significant biclusters in gene expression data. Bioinformatics, 18:136–144. [23] J. Yang, W. Wang, H. Wang, and P. Yu (2002). d-cluster: Capturing subspace correlation in a large data set. Proceedings of 18th International Conference on Data Engineering. [24] R. Peeters (2003). The maximum edge biclique problem is np-complete. Discrete Applied Mathematics, 131:651–654. [25] J. Aguilar (2005). Shifting and scaling patterns from gene expression data. Bioinformatics, 21:3840–3845. [26] H. Turner et al (2003). Improved biclustering of microarray data demonstrated through systematic performance tests, Computational Statistics and Data Analysis, 2003, vol. 48, pages 235-254. [27] T. Murali, S. Kasif (2003). Extracting Conserved Gene Expression Motifs from Gene Expression Data Pacific Symposium on Biocomputing, sullivan.bu.edu, 8, 77-88. -39- -40-