After some days of thinking, I realize that this blog deserved a little bit more attention, so I decided to change the interface and I'am happy about how it looks now.
Hope to see you again in my personal blog.
keep on programming!
Benjamin
Labels
- Bash (6)
- Bioinformatics (20)
- Debian (6)
- Game-Theory (2)
- HMM (1)
- LaTeX (1)
- Linux (19)
- Machine Learning (3)
- Markov Chains (3)
- Octave (1)
- Perl (7)
- R (18)
- Random (4)
- Sequence analysis (3)
- Stochastic messages (13)
- Tutorials (19)
Saturday, August 17, 2013
Friday, August 16, 2013
Accuracy versus F score: Machine Learning for the RNA Polymerases
Hello, today I'm going to show you the difference of using two different common performance measures (useful not only for Machine Learning purposes, is useful in every scientific field). Until now, I have found more the accuracy values than F scores in the performance measuring of some methods which ranges from metaheuristics (Genetic Algorithms fitness functions) to promoter recognition programs, diagnose methods and so on.
But, I would really recommend to avoid using the accuracy measure. The reason is shown below with a nice example in R programming language (all the functions used in the simulation are included, you can download them clicking here).
Case study 1:
Imagine that you are in a Computer Vision project and your task is to "teach" a program to recognize among electric guitars and acoustic guitars showing the program pictures of different guitars.
Suppose that you've already developed that program and now you want to measure the performance of this Boolean classifier (this is for example, you show the program a picture of a an electric guitar, and the program has to decide whether it will recognize and "classify" it as an electric or as an acoustic guitar).
For the function of this post, lets write down some useful concepts
Consider the following:
TP: a true positive is when the program classifies an electric guitar as an electric guitar, we will use the letter "E" to denote the electric guitar "class"
FP: a false positive is when the program classifies an acoustic guitar as an electric guitar, we will use the letter "A" to denote the acoustic guitar "class"
FN: a false negative is when the program classifies an electric guitar as an acoustic guitar
TN: a true negative is when the program classifies an acoustic guitar as an acoustic guitar
Now that we are ready, we shall begin with the calculations
In R, I have simulated the results of the program. Say, for 1,000 electric guitar pictures and 1,000 acoustic guitar pictures
The program prompt the following results:
PREDICTED.E PREDICTED.A
TRUE.E 485 515
TRUE.A 9 991
If you notice, from the 1000 electric guitar pictures, only 485 were labeled as electric (TP=485), the rest were labeled as acoustic (FN=515). I feel bad for the hypothetical programmer of this hypothetical example.
On the other hand, from the 1000 acoustic guitars, 991 were labeled as acoustic (TN=991) and only 9 of them were labeled as electric (FP=9). Well not bad!..... or it is?
The accuracy value of this program is = 0.738
And, for computing the F score is necessary to compute the precision and the recall first, where:
precision = 0.9817814 and recall = 0.485
Then, the F score is equal to 0.6492637
Well, the F scores seems to be more "strict", and in fact it is in comparison of the accuracy performance measure. But this example is not very "cool". Lets pass to the case study 2
Case study 2:
Now we have 1,000 electric guitar pictures and 100,000 acoustic guitar pictures, the confusion matrix of the results are:
PREDICTED.E PREDICTED.A
TRUE.E 493 507
TRUE.A 1017 98983
If you notice, from the 1,000 electric guitar pictures, only 493 were labeled as electric (TP=493), the rest were labeled as acoustic (FN=507)
On the other hand, from the 100,000 acoustic guitars, 98983 were labeled as acoustic (TN=98983) and only 1017 of them were labeled as electric (FP=1017)
Now (cha cha chan!), the performance values are:
Accuracy: 0.9849109
Precision: 0.3264901
Recall: 0.493
F score: 0.3928287
Now you see it?, how come or how is possible that missing almost the 50% of the labels of the electric guitars, the performance of the program in accuracy is almost 0.99?, despite of having a precision and recall not greater than 0.50. Then we have a winner and is the F score measure.
for references visit the following pages:
http://en.wikipedia.org/wiki/Accuracy
http://en.wikipedia.org/wiki/F1_score
http://en.wikipedia.org/wiki/Precision_and_recall
But, I would really recommend to avoid using the accuracy measure. The reason is shown below with a nice example in R programming language (all the functions used in the simulation are included, you can download them clicking here).
Case study 1:
Imagine that you are in a Computer Vision project and your task is to "teach" a program to recognize among electric guitars and acoustic guitars showing the program pictures of different guitars.
Suppose that you've already developed that program and now you want to measure the performance of this Boolean classifier (this is for example, you show the program a picture of a an electric guitar, and the program has to decide whether it will recognize and "classify" it as an electric or as an acoustic guitar).
For the function of this post, lets write down some useful concepts
Consider the following:
TP: a true positive is when the program classifies an electric guitar as an electric guitar, we will use the letter "E" to denote the electric guitar "class"
FP: a false positive is when the program classifies an acoustic guitar as an electric guitar, we will use the letter "A" to denote the acoustic guitar "class"
FN: a false negative is when the program classifies an electric guitar as an acoustic guitar
TN: a true negative is when the program classifies an acoustic guitar as an acoustic guitar
Now that we are ready, we shall begin with the calculations
In R, I have simulated the results of the program. Say, for 1,000 electric guitar pictures and 1,000 acoustic guitar pictures
The program prompt the following results:
PREDICTED.E PREDICTED.A
TRUE.E 485 515
TRUE.A 9 991
If you notice, from the 1000 electric guitar pictures, only 485 were labeled as electric (TP=485), the rest were labeled as acoustic (FN=515). I feel bad for the hypothetical programmer of this hypothetical example.
On the other hand, from the 1000 acoustic guitars, 991 were labeled as acoustic (TN=991) and only 9 of them were labeled as electric (FP=9). Well not bad!..... or it is?
The accuracy value of this program is = 0.738
And, for computing the F score is necessary to compute the precision and the recall first, where:
precision = 0.9817814 and recall = 0.485
Then, the F score is equal to 0.6492637
Well, the F scores seems to be more "strict", and in fact it is in comparison of the accuracy performance measure. But this example is not very "cool". Lets pass to the case study 2
Case study 2:
Now we have 1,000 electric guitar pictures and 100,000 acoustic guitar pictures, the confusion matrix of the results are:
PREDICTED.E PREDICTED.A
TRUE.E 493 507
TRUE.A 1017 98983
If you notice, from the 1,000 electric guitar pictures, only 493 were labeled as electric (TP=493), the rest were labeled as acoustic (FN=507)
On the other hand, from the 100,000 acoustic guitars, 98983 were labeled as acoustic (TN=98983) and only 1017 of them were labeled as electric (FP=1017)
Now (cha cha chan!), the performance values are:
Accuracy: 0.9849109
Precision: 0.3264901
Recall: 0.493
F score: 0.3928287
Now you see it?, how come or how is possible that missing almost the 50% of the labels of the electric guitars, the performance of the program in accuracy is almost 0.99?, despite of having a precision and recall not greater than 0.50. Then we have a winner and is the F score measure.
for references visit the following pages:
http://en.wikipedia.org/wiki/Accuracy
http://en.wikipedia.org/wiki/F1_score
http://en.wikipedia.org/wiki/Precision_and_recall
Saturday, May 25, 2013
Make your LaTex presentations using the Beamer class
Hello, I have been working with this tutorial. All you need to do is download the source files and take a look at the source code and the PDF file.
Download link here
Hope you find LaTex as useful as I do
Benjamin
Download link here
Hope you find LaTex as useful as I do
Benjamin
Sunday, December 2, 2012
Póster presentado en la XIV Escuela de Otoño en Biología Matemática, México
Póster presentado en la XIV Escuela de Otoño en Biología Matemática - 8vo Encuentro de Biología Matemática celebrado en San Luis Potosí, S.L.P, México:
Póster disponible aquí
![]() |
| "Predicción de promotores RNA POL-II en Drosophila melanogaster utilizando propiedades de señal, contexto y estructura a partir de secuencias nucleotídicas" |
Póster disponible aquí
Brownian motion simulation in R
I have based this post on a very useful piece of code which basically is the core of my own implementation of a Brownian Motion simulation in R. The original reference code <- http://landshape.org/enm/r-code-for-brownian-motion/
According to Wikipedia the mathematical model for Brownian motion (also known as random walks) can also be used to describe many phenomena as well as the random movements of minute particles,
such as stock market fluctuations and the evolution of physical characteristics in the fossil record. The simple form of the mathematical model for Brownian motion has the form:
S_t = eS_t-1
where e is drawn from a probability distribution.
The source code is here
After loading the source code, there are two functions:
The first one, brownian will plot in an R graphics window the resulting simulation in an animated way.
The second function, export.brownian will export each step of the simulation in independent PNG files.
Example of running:
> source("brownian.motion.R")
> brownian(500)
According to Wikipedia the mathematical model for Brownian motion (also known as random walks) can also be used to describe many phenomena as well as the random movements of minute particles,
such as stock market fluctuations and the evolution of physical characteristics in the fossil record. The simple form of the mathematical model for Brownian motion has the form:
S_t = eS_t-1
where e is drawn from a probability distribution.
The source code is here
After loading the source code, there are two functions:
The first one, brownian will plot in an R graphics window the resulting simulation in an animated way.
The second function, export.brownian will export each step of the simulation in independent PNG files.
Example of running:
> source("brownian.motion.R")
> brownian(500)
# *******************************
# BROWNIAN MOTION SIMULATION
# December 2012 | Benjamin Tovar
# *******************************
#
# REFERENCES
# http://landshape.org/enm/r-code-for-brownian-motion/
#
# According to Wikipedia the mathematical model for Brownian motion
# (also known as random walks) can also be used to describe many
# phenomena as well as the random movements of minute particles,
# such as stock market fluctuations and the evolution of physical
# characteristics in the fossil record. The simple form of the
# mathematical model for Brownian motion has the form:
#
# S_t = eS_t-1
#
# where e is drawn from a probability distribution.
#
#######################################################################
brownian <- function(n.times){
x <- y <- x.new <- y.new <- x.new.p <- y.new.p <- vector()
for(i in 1:n.times){
# Initialize variables
x <- rnorm(1)
y <- rnorm(1)
# concatenate variables
# to increase the vector size
x.new <- c(x.new,x)
y.new <- c(y.new,y)
# sum the vector numbers
x.new.p <- cumsum(x.new)
y.new.p <- cumsum(y.new)
# plot the model
plot(x.new.p,y.new.p,type="b",
main=paste("Brownian motion simulation in R\nTime =",i,sep=" "),
xlab="x coordinates",ylab="y coordinates",
col=c(rep("gray",i-1),"red"),
pch=c(rep(20,i-1),1))
}
}
# Test the function
# brownian(500)
# ****************************************
# EXPORT BROWNIAN MOTION SIMULATION IMAGES
# ****************************************
export.brownian <- function(n.times){
x <- y <- x.new <- y.new <- x.new.p <- y.new.p <- vector()
for(i in 1:n.times){
# Initialize variables
x <- rnorm(1)
y <- rnorm(1)
# concatenate variables to increase the
# vector size
x.new <- c(x.new,x)
y.new <- c(y.new,y)
# sum the vector numbers
x.new.p <- cumsum(x.new)
y.new.p <- cumsum(y.new)
# plot the model
png(paste("image",i,"png",sep="."),width=600,height=600)
plot(x.new.p,y.new.p,type="b",
main=paste("Brownian motion simulation in R\nTime =",
i,sep=" "),
xlab="x coordinates",ylab="y coordinates",
col=c(rep("gray",i-1),"red"),
pch=c(rep(20,i-1),1))
cat("image",i,"DONE",date(),"\n")
dev.off()
}
}
# Test the function
# export.brownian(500)
Sunday, July 29, 2012
Extracting upstream regions of a RefSeq human gene list in R using Bioconductor
Suppose that you want to do local mapping of upstream regions of a given RefSeq IDs in a particular genome in R using Bioconductor. Download the script here.
In this case, you may take a look at the Bioconductor AnnotationData Packages here: http://www.bioconductor.org/packages/release/data/annotation/
The goal of this post is that for example I have the following RefSeq IDs and want to extract 250 bases upstream of each gene in a single list with another useful information such the entrez.id, the symbol and the gene description.
Before starting, please download the following packages in R:
CODE:
Benjamin.
In this case, you may take a look at the Bioconductor AnnotationData Packages here: http://www.bioconductor.org/packages/release/data/annotation/
The goal of this post is that for example I have the following RefSeq IDs and want to extract 250 bases upstream of each gene in a single list with another useful information such the entrez.id, the symbol and the gene description.
# RefSeqs IDs:
gene.list.refseq <- c("NM_003588","NM_001145436", "NM_001135188","NM_020760","NM_173362", "NM_198393","NM_022736","NM_025074","NM_033449","NM_015726", "NM_022110","NM_016478","NM_020634","NM_002291","NM_000418", "NM_001862","NM_017752","NM_006591","NM_000124","NM_144610")
# How many bases upstream of each gene:
bases.upstream <- 250Before starting, please download the following packages in R:
source("http://bioconductor.org/biocLite.R")
biocLite("BSgenome.Hsapiens.UCSC.hg19")
biocLite("Biostrings")
biocLite("org.Hs.eg.db")
Load the function using:
source("extract.five.utr.sequence.R")
And finally make the computations:
output.sequences <- extract.five.utr.sequence(gene.list.refseq,bases.upstream)CODE:
# ******************************************************************************
# FUNCTION: extract.five.utr.sequence | 29/JULY/2012 | BENJAMIN TOVAR
# ******************************************************************************
extract.five.utr.sequence <- function(gene.list.refseq,
number.bases.upstream=1000){
# *****************************************************************
# RUNNING NOTES: Please download this packages from Bioconductor
# http://www.bioconductor.org/packages/release/data/annotation/
# *****************************************************************
# source("http://bioconductor.org/biocLite.R")
# biocLite("BSgenome.Hsapiens.UCSC.hg19")
# biocLite("Biostrings")
# biocLite("org.Hs.eg.db")
# *****************************************************************
# RUNNING EXAMPLE
# *****************************************************************
#
## Extract 250 bases upstream of each gene in gene.list.refseq
#
# gene.list.refseq <- c("NM_003588","NM_001145436", "NM_001135188","NM_020760","NM_173362",
# "NM_198393","NM_022736","NM_025074","NM_033449","NM_015726",
# "NM_022110","NM_016478","NM_020634","NM_002291","NM_000418",
# "NM_001862","NM_017752","NM_006591","NM_000124","NM_144610")
#
# bases.upstream <- 250
#
# result <- extract.five.utr.sequence(gene.list.refseq,bases.upstream)
# *****************************************************************
# LOAD THE LIBRARIES
# *****************************************************************
cat("Loading libraries",date(),"\n")
# human genome DNA sequences
library(BSgenome.Hsapiens.UCSC.hg19)
# human genome wide annotations
library(org.Hs.eg.db)
# load IDs, symbol and gene descriptions
refseq.id <- toTable(org.Hs.egREFSEQ)
symbol <- toTable(org.Hs.egSYMBOL)
gene.description <- toTable(org.Hs.egGENENAME)
# *****************************************************************
# LOAD THE UPSTREAM SEQUENCES
# *****************************************************************
if(number.bases.upstream <= 1000){
# load the 1000 bases upstream of all genes in the human genome
# in the BSgenome.Hsapiens.UCSC.hg19 package
upstream <- Hsapiens$upstream1000
}
if(number.bases.upstream > 1000 && number.bases.upstream <= 2000){
# load the 1000 bases upstream of all genes in the human genome
# in the BSgenome.Hsapiens.UCSC.hg19 package
upstream <- Hsapiens$upstream2000
}
if(number.bases.upstream > 2000 && number.bases.upstream <= 5000){
# load the 1000 bases upstream of all genes in the human genome
# in the BSgenome.Hsapiens.UCSC.hg19 package
upstream <- Hsapiens$upstream5000
}
if(number.bases.upstream > 5000){
cat("ERROR: The number of bases upstream of 5'UTR is too large (max value = 5000)\n")
return(0);
}
if(number.bases.upstream < 1){
cat("ERROR: The number of bases upstream of 5'UTR cannot be less than 1 nucleotide (min value = 1)\n")
return(0);
}
# extract the names of each gene
names.genes.upstream <- names(upstream)
# extract the refseq of each gene
refseq.upstream.id <- vector("character",length(names.genes.upstream))
for(i in 1:length(names.genes.upstream)){
refseq.upstream.id[i] <- gsub(", ","_",toString(unlist(strsplit(names.genes.upstream[i],
"\\_"))[c(1,2)],sep=""))
}
names(refseq.upstream.id) <- 1:length(refseq.upstream.id)
# *****************************************************************
# CREATE OUTPUT OBJECT
# *****************************************************************
output.params <- c("entrez.id","symbol","gene.description","five.UTR.sequence")
output.list <- list()
for(i in 1:length(gene.list.refseq)){
output.list[[i]] <- list()
for(j in 1:length(output.params)){
output.list[[i]][[j]] <- list()
}
names(output.list[[i]]) <- output.params
}
names(output.list) <- gene.list.refseq
# *****************************************************************
# LET THE COMPUTER DECIDE
# *****************************************************************
cat("Extracting data",date(),"\n")
for(i in 1:length(gene.list.refseq)){
cat(rep(".",1))
# extract the entrez.id of each gene in geneList
output.list[[i]]$entrez.id <- refseq.id[which(refseq.id$accession==gene.list.refseq[i]),]$gene_id
# extract the symbol of each gene in geneList
output.list[[i]]$symbol <- symbol[which(symbol==output.list[[i]]$entrez.id),]$symbol
# extract the gene description of each gene in geneList
output.list[[i]]$gene.description <- gene.description[which(gene.description==output.list[[i]]$entrez.id),]$gene_name
# Return the index of the target genes
index.target.gene <- sequence <- NA;
index.target.gene <- as.numeric(names(refseq.upstream.id[which(refseq.upstream.id==gene.list.refseq[i])]))
# NOTE: some genes have repeated RefSeq.id which corresponds to the same gene in other Chromosomes.
# by using index.target.gene[1] we are selecting only the first RefSeq entry.
sequence <- upstream[index.target.gene[1]]
sequence.length <- nchar(sequence)
start.position <- ((sequence.length-number.bases.upstream)+1)
sequence <- substring(toString(sequence),1:sequence.length,1:sequence.length)
sequence <- sequence[start.position:sequence.length]
output.list[[i]]$five.UTR.sequence <- sequence
}
cat("\n")
cat("Computations DONE",date(),"\n")
return(output.list)
}
Benjamin.
Saturday, June 23, 2012
Handling large FASTA sequence datasets in R: Shuffle and retrieve "n" number of sequences of fixed length from the whole FASTA file and export them in a new FASTA file.
When you are working with large FASTA datasets is probable to find out that the sequences are in sort of a mixed quality (obviously, depending on your scientific question),
I mean for example, imagine that you retrieve the whole collection of exons of a given organism and suppose that the FASTA file is 50mb and there are included ~50,000 DNA sequences but, if you look at them, you may find that there are sequences much larger than others and others will be probably 50 bases long.
Well that's what I mean with mixed quality and therefore, a sort of filter might be very helpful because you may find more informative to put a threshold and say "hey, from the pool of ~50K sequences I only want 5K sequences randomly chosen (from the entire FASTA dataset) and every sequence must have a fixed length, say 1000 bases long".
That's why I wrote some code in R language, it's a function titled "shuffleAndExtract" and you can download the example set and the source here.
Here is the description of the function:
handleFastaDatasets.R
shuffleAndExtract: This function in R is designed to open a fasta file dataset, shuffle the sequences and extract the desired sequences wanted by the user to generate a new dataset of fixed size (number of required sequences) and with the same length for each sequence.
And, after you download the example set and the R source file, you can try to run a very simple example:
NOTE: my implementation depends on the function "seqinr", if is not installed, you may do this before all the magic begin with a simple install.packages("seqinr").
# run example:
source("handleFastaDatasets.R")
shuffleAndExtract("example.fasta",1000,200)
The arguments of the function are:
inputFastaFile: name of the input fasta file
numberOfoutputSeqs: number of desired sequences in the output file
lengthOutputSeqs: fixed length of every sequence in the output file
initialPos: Position where the new window sizing will begin, default = 1
outputFileName: name of the output file, by default will be (e.g): "inputFastaFile.fasta.output.fasta"
CODE:
I mean for example, imagine that you retrieve the whole collection of exons of a given organism and suppose that the FASTA file is 50mb and there are included ~50,000 DNA sequences but, if you look at them, you may find that there are sequences much larger than others and others will be probably 50 bases long.
Well that's what I mean with mixed quality and therefore, a sort of filter might be very helpful because you may find more informative to put a threshold and say "hey, from the pool of ~50K sequences I only want 5K sequences randomly chosen (from the entire FASTA dataset) and every sequence must have a fixed length, say 1000 bases long".
That's why I wrote some code in R language, it's a function titled "shuffleAndExtract" and you can download the example set and the source here.
Here is the description of the function:
handleFastaDatasets.R
shuffleAndExtract: This function in R is designed to open a fasta file dataset, shuffle the sequences and extract the desired sequences wanted by the user to generate a new dataset of fixed size (number of required sequences) and with the same length for each sequence.
And, after you download the example set and the R source file, you can try to run a very simple example:
NOTE: my implementation depends on the function "seqinr", if is not installed, you may do this before all the magic begin with a simple install.packages("seqinr").
# run example:
source("handleFastaDatasets.R")
shuffleAndExtract("example.fasta",1000,200)
The arguments of the function are:
inputFastaFile: name of the input fasta file
numberOfoutputSeqs: number of desired sequences in the output file
lengthOutputSeqs: fixed length of every sequence in the output file
initialPos: Position where the new window sizing will begin, default = 1
outputFileName: name of the output file, by default will be (e.g): "inputFastaFile.fasta.output.fasta"
CODE:
################################################################################
shuffleAndExtract <- function(inputFastaFile,
numberOfoutputSeqs,
lengthOutputSeqs,
initialPos=1,
outputFileName = paste(inputFastaFile,"output",
"fasta",sep=".")
){
#
# handleFastaDatasets.R
#
# This function in R is designed to open a fasta file dataset, shuffle the
# sequences and extract the desired sequences wanted by the user to generate
# a new dataset of fixed size (number of required sequences) and with the
# same length for each sequence.
#
# Author: Benjamin Tovar
# Date: 22/JUNE/2012
#
################################################################################
# run example:
# source("handleFastaDatasets.R")
# shuffleAndExtract("example.fasta",1000,200)
# inputFastaFile: name of the input fasta file
# numberOfoutputSeqs: number of desired sequences in the output file
# lengthOutputSeqs: fixed length of every sequence in the output file
# initialPos: Position where the new window sizing will begin, default = 1
# outputFileName: name of the output file, by default will be (e.g):
# "inputFastaFile.fasta.output.fasta"
cat("*** Starting computations |",date(),"****\n")
# Load the seqinr package
require(seqinr)
# Load the large seq and not shuffled dataset
inputSeqs <- read.fasta(inputFastaFile)
cat("\tProcessing for",length(inputSeqs),"sequences |",date(),"\n")
# Extract the length of every sequence and store the results in a vector.
inputSeqsSize <- rep(NA,length(inputSeqs))
for(i in 1:length(inputSeqs)){
inputSeqsSize[i] <- summary(inputSeqs[[i]])$length
}
# Extract the index of the sequences which are longer than threshold
inputSeqsLongSeqIndex <- which(inputSeqsSize > (lengthOutputSeqs+initialPos))
# randomly pick numberOfoutputSeqs indexes that will be used to create
# the output dataset
inputSeqsIndex <- sample(inputSeqsLongSeqIndex,numberOfoutputSeqs,rep=F)
# Store the Fasta header of each selected sequence in a vector
inputSeqsIndexNames <- rep(NA,numberOfoutputSeqs)
# create output object
outputSeqs <- list()
for(i in 1:numberOfoutputSeqs){
# Extract the fasta headers
inputSeqsIndexNames[i] <- attr(inputSeqs[[inputSeqsIndex[i]]],"name")
# Extract the sequence
outputSeqs[[i]] <- inputSeqs[[inputSeqsIndex[i]]][initialPos:((initialPos+lengthOutputSeqs)-1)]
}
# Export the sequences in a new fasta file
write.fasta(outputSeqs,inputSeqsIndexNames,outputFileName)
cat("\n*** DONE |",date(),"****\n")
}
# 22 Jun 2012 | Benjamin Tovar
Benjamin
Subscribe to:
Posts (Atom)


