terça-feira, 16 de dezembro de 2014

Resumo de Otimização: Mínimos Quadrados

Atualização: veja a parte 2 deste texto, onde apresento um método de solução direta do problema e uma formulação regularizada chamada Ridge Regression que evita overfitting. O método de Mínimos Quadrados (Least Squares) é utilizado para resolver sistemas "super"-determinados (ou impossíveis) , i.e. em que existem mais restrições que variáveis desconhecidas. Apesar de não ser possível encontrar uma solução que respeite todas as restrições simultaneamente, é possível calcular uma aproximação. O método de Mínimos Quadrados busca uma solução que minimize a a soma dos quadrados das diferenças entre o valor predito pelo modelo e o valor desejado. 

Dados pares de observações $(x_j, y_j), 1 \leq j \leq m, x_j \in \mathbb{R}^n, m > n$, queremos encontrar uma função $g(x; \theta), \theta \in \mathbb{R}^k$ tal que $g(x_j; \theta) = y_j$ para uma escolha adequada dos parâmetros $\theta$. A função $g(x; \theta)$ é o modelo utilizado e precisa ser definido previamente.

Idealmente, o modelo $g(x; \theta)$ seria flexível o suficiente para representar a transformação desejada. Na prática, porém, o modelo $g(x; \theta)$ pode somente aproximar o valor correto $y_j$ a partir de $x_j$. Desta forma, podemos definir o erro de aproximação do par $(x_j, y_j)$ como

\[ r_j(\theta) = g(x_j; \theta) - y_j \]

e minimizar a função objetivo

\[ f(\theta) =  \frac{1}{2}\sum^m_j [r_j(\theta)]^2 = \frac{1}{2}\sum^m_j [  g(x_j; \theta) - y_j    ]^2. \]

Ao minimizar $f(\theta)$ encontramos o vetor de parâmetros $\theta$ que "melhor" ajusta o modelo $g(x; \theta)$ aos dados $(x_j, y_j)$. Neste caso, "melhor" é definido como o vetor $\theta$ que minimiza a soma do quadrado dos erros. Por isto o nome de método de Mínimos Quadrados.

Justificativa estatística

Suponha que os $r_j(\theta)$ são independentes e identicamente distribuídos com média 0, variância $\sigma^2$ e função densidade de probabilidade $g_\sigma$. Sob estas condições, a probabilidade de observar os $r_j(\theta)$ correspondentes ao conjunto de dados $(x_j, y_j)$, dadas a variância $\sigma$ e o vetor de parâmetros $\theta$ é:

\[p( (x, y) ; \theta ; \sigma) = \prod_j^m g_\sigma( r_j(\theta) )  = \prod_j^m g_\sigma( g(x_j; \theta) - y_i ) \]

Fixadas as observações $(x_j, y_j)$ e $\sigma$, o valor "mais provável" de $\theta$ é o que maximiza $p( (x, y) ; \theta ; \sigma)$. Este estimador para $\theta$ é chamado de Estimador de Máxima Verossimilhança.

Suponha, então, que a distribuição dos $r_j$ é normal. Portanto,

\[ g_\sigma(r) = \frac{1}{\sqrt{2\pi \sigma^2}} \mathrm{exp}(-\frac{r^2}{2\sigma^2}), \]

e então,

\[p( (x, y) ; \theta ; \sigma) =   \frac{1}{(2\pi\sigma^2)^{m / 2}} \mathrm{exp}(-\frac{1}{2\sigma^2}  \sum_j^m [g(x_j; \theta) - y_i )]^2  ). \]

Para maximizar $p( (x, y) ; \theta ; \sigma)$ (dado $\sigma^2$ fixo) é necessário minimizar $\sum_j^m [g(x_j; \theta) - y_i )]^2$. Portanto, a estimativa de $\theta$ obtida pelo método de Mínimos Quadrados equivale ao estimador de máxima verossimilhança de $\theta$ (supondo que os erros $r_j$ são i.i.d. com distribuição normal de média 0 e variância fixa $\sigma^2$).

Modelos Lineares

Diversos problemas podem ser modelados utilizando funções $g(x; \theta)$ lineares em $\theta$. Podemos, portanto, escrever os resíduos como $r_j(\theta) = x_j^T\theta - y_j$.

Seja $J \in \mathbb{R}^{m\times n}$ tal que

\[ J =

\begin{pmatrix}
x_1^T \\
\dots \\
x_m^T\\
\end{pmatrix}, \]

então o problema de mínimos quadrados se reduz a minimizar a função

\[ f(\theta) = \frac{1}{2} || J\theta - y ||_2^2 \]

Modelos lineares são vantajosos pois a função acima pode ser minimizada globalmente. Isto não é necessariamente verdade para modelos não lineares em $\theta$.

Note que a função $g(x; \theta)$ deve ser linear em $\theta$, mas não necessariamente em $x$. Logo, a função

\[ g(x; \theta) = {x^{(1)}}^2  \theta_{(1)} + x^{(1)}x^{(2)}\theta_{(2)} \]

é um modelo válido para a estimação linear, pois ela equivale a construir um novo conjunto de dados $(x'_j, y_j)$, onde $x'_j = ({x^{(1)}_j}^2, x_j^{(1)}x_j^{(2)})$, e fazer a minimização linear "comum".

Exemplos usando Python

A biblioteca Scipy possui tanto a implementação do Método de Mínimos Quadrados para o caso linear quanto para o caso geral. Neste texto mostrarei como utilizar a função numpy.linalg.lstsq para estimar modelos lineares.

Iremos estimar duas funções diferentes. Ambas podem ser estimadas usando modelos lineares. A função $f_1$ é um polinômio de segundo grau e a $f_2$ é uma função de duas variáveis.

\[  f_1(x) = 2x^2 + 5x + 7 \]

\[  f_2(x_1, x_2) = 0.3x^3 - 0.2y^2 + 3y - xy + 5 \]


Estimação de polinômios 

 

Utilizaremos três modelos para estimar $f_1$:

\[ g_1(x) = p_1x + p_2 \]
\[ g_2(x) = p_1x + p_2x^2 + p_3 \]
\[ g_3(x) = p_1x + p_2x^2 + p_3x^3 + p_4 \]

 É esperado que o modelo $g_1$ possua erro grande, pois um polinômio de grau 1 não consegue aproximar um polinômio de grau 2. Por outro lado, tanto $g_2$ quanto $g_3$ deverão obter boas aproximações, sendo que em $g_3$ o componente $x^3$ deverá ser próximo de 0.

Primeiramente, iremos gerar nosso conjunto de observações de $f_1$. Em cada observação também adicionaremos um pequeno erro.

x_data = [1, 4, 7, 8, -2, 5, 6, 12, -3, -5, -10]
y_data = [2 * x*x + 5*x + 7 - (random.random() * 5 - 2.5) for x in x_data]

Agora, iremos definir a matrix $J$ para cada um dos modelos e aplicar a função lstsq para estimar os parâmetros de cada modelo.

m =  len(x_data)
x2 = np.array([x*x for x in x_data]).reshape((m, 1))
x3 = np.array([x*x*x for x in x_data]).reshape((m, 1))
x_data = np.reshape(x_data, (m, 1))
y_data = np.reshape(y_data, (m, 1))

ones = np.ones(m).reshape(m, 1)

J1 = np.hstack([x_data, ones])
J2 = np.hstack([x2, x_data, ones])
J3 = np.hstack([x3, x2, x_data, ones])

theta_g_1 = np.linalg.lstsq(J1, y_data )
theta_g_2 = np.linalg.lstsq(J2, y_data )
theta_g_3 = np.linalg.lstsq(J3, y_data )

Os resultados obtidos podem ser vistos nas figuras abaixo:






Como esperado, a estimação linear foi bem ruim e a quadrática deu resultados quase perfeitos. O polinômio de grau 3 também teve resultados bons e apresentou um coeficiente bem pequeno para o termo $x^3$.

Estimação (linear) de funções de várias variáveis



Utilizaremos 2 modelos para estimar a função $f_2$:

\[ g_1(x, y) = \theta_1 x + \theta_2 y + \theta_3 xy + \theta_4\]
\[ g_2(x, y) = \theta_1 x^2 + \theta_2 x y + \theta_3 y^2 + \theta_4 x + \theta_5 y + \theta_6\]
\[ g_3(x, y) = \theta_1 x^3 + \theta_2 x^2 y + \theta_3 x y^2 + \theta_4 y^3 + \theta_5 x^2 + \theta_6y^2 + \theta_7xy + \theta_8x + \theta_9y + \theta_{10}\] 

Primeiramente, geramos as observações usando o código abaixo. Note que é necessário um número muito maior de pontos para estimar funções mais complexas.


data = np.array([(random.randint(-50, 50), random.randint(-50, 50)) for i in range(100)])
y_data = [0.3*x**3 - 0.2*y**2 + 3*y - x*y + 5 - (random.random() * 5 - 2.5) for (x, y) in data]

Após, geramos os vetores com as componentes de cada modelo e as matrizes $J_1, J2$ e $J_3$.


m = data.shape[0]
x3  = np.array([x**3 for (x, y) in data]).reshape((m, 1))
x2  = np.array([x**2 for (x, y) in data]).reshape((m, 1))
x1   = np.array([x for (x, y) in data]).reshape((m, 1))
y3  = np.array([y**3 for (x, y) in data]).reshape((m, 1))
y2  = np.array([y**2 for (x, y) in data]).reshape((m, 1))
y1   = np.array([y for (x, y) in data]).reshape((m, 1))
x2y = np.array([x**2 * y for (x, y) in data]).reshape((m, 1))
y2x = np.array([x * y**2 for (x, y) in data]).reshape((m, 1))
xy  = np.array([x*y for (x, y) in data]).reshape((m, 1))
ones= np.ones(m).reshape((m, 1))

J_1 = np.hstack([x1, y1, xy, ones])
J_2 = np.hstack([x2, xy, y2, x1, y1, ones])
J_3 = np.hstack([x3, x2y, y2x, y3, x2, y2, xy, x1, y1, ones])

theta_g_1, err1, _, _ = np.linalg.lstsq(J_1, y_data)
theta_g_2, err2, _, _ = np.linalg.lstsq(J_2, y_data)
theta_g_3, err3, _, _ = np.linalg.lstsq(J_3, y_data)

Os resultados obtidos foram os seguintes:
 Erro: 3.73790848e+09
 Erro: 3.64574253e+09
Erro:  204.59062094


Os primeiros dois modelos, mais simples, resultaram em erros grandes pois eles não possuem algumas componentes do modelo original. Já o terceiro modelo obteve resultados muito bons, porém ele contém uma quantidade muito maior de parâmetros que o modelo original. Isto ocorre pois o modelo original, em geral, não é conhecido e acabamos incluindo componentes irrelevantes para a estimação de $y_i$.

Uma desvantagem do método de Mínimos Quadrados é que a minimização feita dificilmente zera algum $\theta_i$, pois ele pode super ajustar a curva utilizando pequenos coeficientes em componentes que podem ser irrelevantes. Desta maneira, o método não é capaz de detectar quais parâmetros/características são relevantes para um dado problema.

Comentários finais

A estimação utilizando o método de Mínimos Quadrados otimiza os parâmetros de um modelo de modo a minimizar a soma dos erros ao quadrado. Este método encontra mínimos globais se o modelo utilizado for linear (nos parâmetros a serem estimados) e é vantajoso quando se conhece ou se tem alguma intuição sobre a forma analítica do modelo original dos dados.
Atualização: veja a parte 2 deste texto, onde apresento um método de solução direta do problema e uma formulação regularizada chamada Ridge Regression que evita overfitting.





segunda-feira, 14 de julho de 2014

Trabalho remoto com Linux - Impressão

Neste post irei mostrar alguns comandos do linux para imprimir arquivos em um sistema remoto. É claro que estes comandos funcionam também em qualquer computador com Linux, mas eles são especialmente úteis quando nossos arquivos ficam guardados em um servidor e são disponibilizados via NFS ou SSH. Para rodá-los é necessário estar logado (usando SSH) em uma das máquinas de sua rede.

É importante lembrar que toda operação é executada nas impressoras conectadas à rede em que você está logado, ou seja, não é possível usá-los para imprimir um arquivo remoto em uma impressora na sua casa, por exemplo.

Listar impressoras conectadas

Para listar as impressoras, use o comando abaixo. Todos os comandos subsequentes recebem como parâmetro uma das impressoras listadas usando este comando.

$> lpstat -p -d

Ver a fila de impressão

 $> lpq -P impressora

Enviando trabalhos para impressão
$> lpr -Pimpressora arquivo.PDF

A opção page-range permite escolher um intervalo de páginas a serem impressas.

$> lpr -Pimpressora arquivo.PDF -o page-ranges=S-E

É só substituir S pelo número da primeira página e E pelo número da última.

Opções de impressão

Para listar as opções disponíveis execute

$> lpoptions -d impressora -l

Para ajustar a opção escolhida use

$> lpoptions -d impressora -o Opção=Valor

Esta opção é muito útil para fazer a impressora imprimir imagens coloridas em níveis de cinza. Na impressora que está disponível em minha rede isto é possível configurando a opção ColorMode como Gray usando o comando abaixo.

$>  lpoptions -d impressora -o ColorModel=Gray

A partir deste momento, suas as impressões feitas terão imagens impressas em níveis de cinza. Para garantir que a impressão saia realmente em preto e branco, eu costumo executar este comando logo antes de usar o lpr.

Para voltar a imprimir colorido use

$>  lpoptions -d impressora -o ColorModel=CMYK


Veja também:
Como deixar processos rodando sem estar logado.








sexta-feira, 30 de maio de 2014

Resumo de Local Binary Patterns

Local Binary Patterns (LBP) são descritores locais de textura propostos em [1] baseados na suposição de que a informação de uma textura é dividida em dois aspectos complementares: padrão e intensidade.

O LBP original considerava uma vizinhança 3x3 em torno de cada pixel e, para cada pixel, comparava-o com o pixel central e atribuía 1 para o pixel se ele é maior ou igual ao pixel central e 0 caso contrário. O código LBP de cada pixel é calculado como um número de 8 bits em que o limiar de cada pixel recebe os pesos abaixo. Por fim, é feito um histograma dos códigos LBP calculados. Este histograma representa a textura presente na imagem.

Pesos para a codificação do padrão contido em uma janela 3x3.

A formulação proposta em [2] apresenta um LBP mais geral baseado em vizinhanças circulares e com um número arbitrários de pontos.

Vizinhança circular usada no LBP genérico.


Seja I(x, y) uma imagem em níveis de cinza, gc o nível de cinza de um ponto arbitrário (x, y) da imagem e P o número de pontos amostrados à distância R de (x, y).  Definimos os pontos gp = I(xp, yp), onde

xp = x + R cos(2πp/P),
yp = y - R sin(2πp/P).

Os valores de I(x, y) são interpolados bilinearmente toda vez que (x, y) não estiverem no centro de um pixel.

Suponha que a textura da imagem I possa ser caracterizada pela distribuição conjunta dos P+1 pixels:

T = t(gc, g0, ..., gP-1).

Sem perda de generalidade,

T = t(gc, g0 - gc, ..., gP-1 - gc)

Suponha que o valor do ponto central gc é estatisticamente independente das diferenças, resultando em

T ≈ t(gc)t(g0 - gc, ..., gP-1 - gc)

Desta maneira, a distribuição t(g0 - gc, ..., gP-1 - gc) pode ser usada para caracterizar o padrão da textura. Porém, estimar esta distribuição multi variada com precisão pode ser difícil. Para tornar as diferenças gi - gc robustas à variações nos níveis de cinza e melhorar a estimação de t, consideramos somente o sinal das diferenças. A distribuição estimada é:

t(s(g0 - gc), ..., s(gP-1 - gc))

O código LBP final é definido como

LBPP,R(xc, yc) = ∑ s(gp - gc)2p.

e codifica cada padrão observado como um número binário de P bits. Desta maneira, a distribuição dos padrões LBPP,R(xc, yc) aproxima a textura original T

T ≈ t(LBPP,R(xc, yc)).


A partir deste LBP genérico foram propostos diversas outras variantes deste métodos [3, 4]. Algumas aplicações notáveis do LBP são a segmentação não supervisionada de textura [5, 6] e a localização de faces [7].

Referências:

[1] Timo Ojala, Matti Pietikäinen, David Harwood, A comparative study of texture measures with classification based on featured distributions, Pattern Recognition, Volume 29, Issue 1, January 1996,

[2] Ojala, Timo, Matti Pietikainen, and Topi Maenpaa. "Multiresolution gray-scale and rotation invariant texture classification with local binary patterns." Pattern Analysis and Machine Intelligence, IEEE Transactions on 24.7 (2002): 971-987.

[3] Zhao, Guoying, and Matti Pietikainen. "Dynamic texture recognition using local binary patterns with an application to facial expressions." Pattern Analysis and Machine Intelligence, IEEE Transactions on 29.6 (2007): 915-928.

[4] Zhu, Chao, C-E. Bichot, and Liming Chen. "Multi-scale color local binary patterns for visual object classes recognition." Pattern Recognition (ICPR), 2010 20th International Conference on. IEEE, 2010.

 [5] Ojala, Timo, and Matti Pietikäinen. "Unsupervised texture segmentation using feature distributions." Image Analysis and Processing. Springer Berlin Heidelberg, 1997.

 [6] Ojala, Timo, and Matti Pietikäinen. "Unsupervised texture segmentation using feature distributions." Pattern Recognition 32.3 (1999): 477-486.

[7] Hadid, Abdenour, Matti Pietikainen, and Timo Ahonen. "A discriminative feature space for detecting and recognizing faces." Computer Vision and Pattern Recognition, 2004. CVPR 2004. Proceedings of the 2004 IEEE Computer Society Conference on. Vol. 2. IEEE, 2004.

terça-feira, 19 de novembro de 2013

Resumo do artigo "The ICDAR 2013 Music Scores Competition: Staff Removal"

O artigo "The ICDAR 2013 Music Scores Competition: Staff Removal" apresenta os resultados da competição de remoção de compasso ocorrida no ICDAR 2013. Os autores descrevem o conjunto de imagens usado e os processamentos realizados para degradar as imagens para que elas se tornem similares a documentos históricos.  Também são apresentados os resultados da competição.

(Este resumo foca na descrição do conjunto de dados e nas métricas de avaliação de desempenho. Algumas informações foram retiradas do artigo "The ICDAR/GREC 2013 Music Scores Competition on Staff Removal")

O conjunto de dados utilizado na competição foi o CVC-MUSCIMA, que contém 1000 imagens de 20 partituras escritas por 50 músicos diferentes. Cada músico transcreveu as mesmas 20 páginas. Este conjunto de dados foi submetido à duas operações de degradação das imagens e as imagens são oferecidas tanto em binário como em níveis de cinza.

A primeira degradação adiciona ruído local de modo a imitar os traços de documentos antigos. São adicionados defeitos como pequenos borrões de tinta e falhas "brancas" nos traços da imagem.


A segunda deformação simula a digitalização de documentos deteriorados adicionando pequenas dobras e seções amassadas na imagem.





O conjunto de treinamento foi dividido em três partes:
  1. TrainingSubset1: 1000 imagens geradas usando o modelo de distorção 3D com 2 meshes diferentes;
  2. TrainingSubset2: 1000 imagens geradas com 3 níveis de ruído local;
  3. TrainingSubset3: 2000 imagens geradas com combinações de distorção 3D e ruído local. Os parâmetros são os mesmos usados nos itens 1 e 2.
O conjunto de testes também foi dividido em 3 partes:
  1. TestSubset1: 500 imagens geradas usando o modelo de distorção 3D com 2 meshes diferentes dos do treinamento;
  2. TestSubset2: 500 imagens geradas com os mesmos 3 níveis de ruído local;
  3. TestSubset3: 1000 imagens geradas com combinações de distorção 3D e ruído local. Os parâmetros são os mesmos usados nos itens 1 e 2 dos conjuntos de teste.

Os autores utilizaram 5 medidas de erro: Acurácia, Precisão, Recall, F-measure e Especificidade.

(Acurácia = taxa de erro, Precisão = TP/(TP + FP), Recall = TP/(TP + FN), Especificidade = TN/(TN + FP), F-measure= 2* (Precisão * Recall)/(Precisão + Recall) )

Os resultados de cada método podem ser vistos na tabela da última página do artigo [2].

Referências completas:
  1. Visaniy, M.; Kieu, V.C.; Fornes, A.; Journet, N., "ICDAR 2013 Music Scores Competition: Staff Removal," Document Analysis and Recognition (ICDAR), 2013 12th International Conference on , vol., no., pp.1407,1411, 25-28 Aug. 2013. [Download]
  2. V. Kieu, A. Fornes, M. Visani, and N. Journet, “The ICDAR/GREC 2013 Music Scores Competition on Staff Removal,” in 10th IAPR International Workshop on Graphics RECognition (GREC 2013), Bethlehem, PA, USA. [Download]

sábado, 12 de outubro de 2013

Trabalho remoto com Linux - Screen

Os sistemas baseados em Linux oferecem diversas facilidades para a criação de sessões remotas. Uma das grandes vantagens do trabalho remoto é a possibilidade de utilizar (e dividir com vários usuários) computadores com alto poder de processamento. Isto é especialmente importante na academia, pois frequentemente precisamos executar experimentos ou simulações demoradas e que demandam grande poder computacional. Neste post irei apresentar o básico sobre o screen, uma ferramenta do Linux que permite que um usuário deixe um programa rodando em uma máquina mesmo sem estar logado nela.

Primeiramente, logue por ssh em uma máquina remota de sua escolha e execute no terminal:

$> screen

O comando screen cria um novo terminal que pode ser desvinculado da sua sessão ssh. Ou seja, a sessão do screen continua aberta mesmo que você se desconecte ou que a conexão caia. Para demonstrar esta capacidade, digite o seguinte comando no terminal.

$> sleep 120; echo "Terminou"

Este comando imprimirá na tela "Terminou" após 2 minutos. Agora pressione as seguintes teclas.

(Ctrl + A) e em seguida D

Seu terminal do screen foi minimizado e você está de volta à sua sessão ssh usual. Só para deixar o exemplo mais real, se desconecte da máquina e conecte novamente.

Ao reconectar na máquina remota, precisamos indicar que desejamos retomar nossa sessão do screen. Para fazer isto use o seguinte comando:

$> screen -r

Agora estamos de volta ao terminal que abrimos anteriormente e o texto "Terminou" deverá estar escrito na tela. Note que toda vez que executamos o comando screen sem parâmetros será aberta uma nova sessão. Pessoalmente, costumo usar somente uma sessão por máquina. Podemos listar as sessões do screen usando o comando

$> screen -ls

e restaurar uma sessão específica usando

$> screen -r NOME_DO_SCREEN

Assim como uma janela do konsole ou gnome-terminal pode conter várias abas, uma sessão do screen também pode abrigar diversos terminais diferentes. Somente um terminal fica visível, mas todos estão sendo executados em paralelo. Para criar um novo terminal em seu screen aperte

(Ctrl + A) e em seguida C

Para ver quais terminais estão abertos em sua sessão use

(Ctrl + A) e em seguida W

O terminal com uma * ao lado do nome é o que está visível atualmente. Para navegar entre os terminais use

(Ctrl + A) e em seguida N

para ir para o próximo (Next) terminal e

(Ctrl + A) e em seguida P

para ir para o terminal anterior (Previous).

Estes são os principais comandos do screen para a execução de programas demorados em máquinas remotas. Deixe um comentário para qualquer dúvida ou esclarecimento. Sugestões também são benvindas.

Veja também:
Como imprimir em máquinas remotas.

segunda-feira, 30 de setembro de 2013

Review (atrasado) do Windows 8

As reações ao lançamento do Windows 8 foram, em geral, negativas. A InfoWorld chegou a dizer que o "Windows 8 é garantia de decepção para quase todos". Como existem tantas opiniões sobre o assunto, resolvi escrever o que estou achando do Windows 8 que veio pré-instalado no meu notebook.

Primeiramente, sou um usuário bem experiente. Meu antigo notebook veio com Windows 7 pré-instalado, mas usei praticamente só Ubuntu nos últimos dois anos. Também uso Ubuntu no laboratório em que trabalho e posso dizer que tenho bastante experiência tanto com Linux como com Windows.

Impressão Inicial

Passei meus primeiros 10 minutos descobrindo, basicamente, como não usar a nova interface do Windows 8 e manter o desktop visível o máximo de tempo possível. Também demorei algum tempo até achar o Painel de Controle. O item "Configurações" da interface nova não é equivalente e mostra bem menos opções. 

Após este primeiro contato, usar o Windows 8 no modo Desktop é igualzinho a usar o Windows 7, só que mais rápido. Aliás, a agilidade nas tarefas em geral está bem maior no novo Windows e isto é especialmente perceptível ao ligar e desligar o notebook. A opção de suspender, então, ficou visivelmente mais rápida e quase parece que o computador nunca desliga.

O Windows 8 no modo desktop não é muito diferente do Windows 7.

Muito se falou da ausência do menu Iniciar. Até agora, posso dizer que não sinto falta nenhuma dele. Em vez de procurar o nome de um programa no menu, agora eu aperto a tecla "Windows" e começo a digitar o nome do programa que quero abrir. O Windows 8 mostra uma lista de programas que contém a minha busca e na maioria das vezes nem preciso digitar o nome até o fim. É só digitar o começo e apertar Enter. Muito melhor, na minha opinião.

Não irei fazer comentários sobre o IE novo pois nunca o utilizei. Meu navegador favorito é o Firefox e ele foi o primeiro programa que instalei. Também não posso falar muito sobre a interface nova (chamada de Modern pela Microsoft), já que, tirando o atalho que comentei acima, não encontrei muita utilidade para ela.

 Programação

Como faço doutorado em Computação, uma das minhas principais atividades é programar (a outra é ler artigos). Sempre que posso programo em Python, porém frequentemente programo em C para minhas pesquisas. 

Python tem um suporte curioso a Windows. Apesar do instalador funcionar super bem, programas para gerenciamento de pacotes, como o pip, são bem chatos de instalar. Além disto, o pip tem sérios problemas em compilar extensões nativas, como o Numpy, principalmente por depender de uma instalação funcionando do Visual C++. Felizmente existe este site, feito pelo Christoph Gohlke, que contém uma quantidade impressionante de pacotes pré-compilados para Windows.

Se você não for usar o Visual Studio é bem provável que você tenha dificuldades em programar em C em Windows, especialmente se estiver acostumado com Linux. Existem distribuições do gcc e similares para Windows (MingW), porém a experiência é muito pior que no Linux (especialmente por causa do péssimo terminal do Windows). Por estar acostumado com meu Ubuntu, preferi então instalar uma máquina virtual e escolhi o VMware Player. Instalei a distribuição Lubuntu, que nada mais é que o Ubuntu com a interface gráfica LXDE, que é bem mais leve que a padrão do Ubuntu.

A grande vantagem de se utilizar o VMware player é que ele possui o modo Unity, que faz com que as janelas da máquina virtual apareça lado a lado com as janelas do sistema operacional nativo. Isto torna a utilização muito mais prática. Para lançar programas na VM basta apertar Ctrl+Shift+U que aparece um menu com todos os programas instalados na sua VM.

Demonstração do VMware Unity. Janelas da minha VM Linux e do Windows compartilhando o mesmo desktop!


Até agora, o desempenho tem sido bom. A velocidade da VM é boa e é muito prático poder usar o que cada sistema tem de melhor ao mesmo tempo.

Conclusão

Ao contrário da maioria da impressa de tecnologia, eu não estou tendo nenhum grande problema com o Windows 8. O sistema é rápido e, após uma breve adaptação, consigo fazer tudo o que preciso sem dificuldades. A experiência que tenho com outros sistemas certamente me ajudou na adaptação, porém achei que, se ignorarmos a nova interface, o Windows 8 é um ótimo sistema operacional.

terça-feira, 24 de setembro de 2013

Resumo do Artigo "Staff Detection with Stable Paths"

 O artigo "Staff Detection with Stable Paths" de Cardoso et al. apresenta um método para a identificação do compasso em imagens de partituras utilizando caminhos em grafos. Segundo os autores, as abordagens anteriores utilizam somente informações locais das imagens sem considerar seu contexto. Em especial, os autores não conhecem trabalhos que explorem o fato das linhas serem os componentes mais largos da imagem.

O método apresentado trata a imagem como um grafo cujos vértices são os pixels da imagem e as arestas conectam pixels vizinhos. O peso das arestas leva em conta tanto a cor como outras propriedades contextuais de imagens de partituras. Supondo que caminhos contendo pixels pretos são menos custosos que caminhos com pixels brancos, as linhas do compasso são caminhos com menor custo que conectam as duas margens da página e que possuem somente um vértice de cada coluna. Iterando este algoritmo é possível encontrar todas as linhas de uma imagem.

Os autores definem um caminho Ps, t como um caminho estável (Stable Path) se Ps, t é, ao mesmo tempo, o caminho mais curto entre o pixel s e sua margem oposta e o caminho mais curto entre o pixel t e sua margem oposta. O algoritmo apresentado para calcular os caminhos estáveis possui complexidade similar ao de computar os caminhos ótimos entre as margens. Não existe garantia que o algoritmo encontrará um caminho estável para cada linha do compasso. Por isto, o método é iterado diversas vezes na imagem, apagando as linhas encontradas anteriormente. Uma etapa final de pós-processamento descarta linhas redundantes e agrupa as linhas em compassos. Linhas que não fazem parte de um compasso são descartadas.

A avaliação do método é feita utilizando as imagens da base do MusicStaves. O algoritmo apresenta bons resultados na comparação com o algoritmo de detecção de linhas apresentado em Dalitz et al2008. Os autores também testam o efeito da utilização deste algoritmo no lugar do implementado no MusicStaves para a remoção de compasso e obtém resultados competitivos com o Skeleton (apresentado em Dalitz et al2008 e que não detecta as linhas explicitamente).


Referência completa: dos Santos Cardoso, J.; Capela, A.; Rebelo, A.; Guedes, C.; Pinto da Costa, J., "Staff Detection with Stable Paths," Pattern Analysis and Machine Intelligence, IEEE Transactions on , vol.31, no.6, pp.1134,1139, June 2009 [Download]