Resourceful Web

Todos sabem que, com o tempo, os frameworks web evoluem. Porém, o que poucas pessoas percebem é que além das mudanças nas APIs e na estrutura dos programas feitos com o framework, há uma mudança também nas idéias dos desenvolvedores e até mesmo nas metáforas que o sistema usou para definir-se. E o Rails não é exceção.

Por exemplo, no Ruby on Rails versão 1.x, a idéia do framework era a construção de aplicações web. Para tal, a idéia era que a aplicação fosse simples e divertida de desenvolver. Além disso, havia a idéia de web-services, XML-RPC e SOAP que nunca pegaram direito no mundo Rails (mas que estavam presentes na versão 1.x). Depois, na versão 2.x, surgiu o conceito de RESTful (em contraponto aos web-services do Rails 1) e, junto com ele, o conceito de “resource” ou “recurso”. Já no Rails 3, surgiu a idéia de separar o Javascript do HTML usando o conceito de Unobtrusive Javascript (Javascript não-intrusivo), e junto com essa idéia, veio a substituição do prototype pelo jQuery (que torna certas operações envolvendo AJAX mais fáceis). Junto também com a substituição por jQuery, o scaffold passou a fazer os controllers responderem por HTML e JSON, ao invés de HTML e XML como no rails 2.x.

E é essa a mudança mais importante.

Vamos começar pensando: qual seria o motivo de renderizar um JSON? A resposta é simples: JSON é mais fácil de ser entendido pelo browser, por Javascript, e por aplicativos de terceiros tais como em iOS ou Android. Antes, responder por XML não tinha aplicação real nenhuma nos próprios aplicativos Rails, e ficavam apenas como forma de comunicação com sistemas de terceiros (o velho “big design up front“) que nem sempre ocorriam. E hoje, renderizar JSON está muito pouco utilizado mesmo no mundo Rails, e há um motivo para isso:

Não sabemos o que é um “resource”.
(more…)

Redes Neurais – Parte 3

Ok, vamos finalmente para a terceira parte sobre Redes Neurais (e também, aonde será apresentado o código completo de uma rede neural em Ruby). Este post será sobre treinamento de redes neurais, especificamente sobre o treinamento dos pesos que saem dos neurônios de entrada e vão para os neurônios ocultos da rede. Antes de mais nada, vamos relembrar nosso desenho da rede neural:

Neural

Já vimos no post anterior que para achar o valor que MAXIMIZA a função de custo, usamos o métoodo chamado de “gradiente”. O método “gradiente” usa derivadas parciais, e como vamos achar o valor de um peso que sai do neurônio de entrada para o neurônio da camada oculta, precisamos calcular a derivada parcial da função de custo em relação a um destes pesos. Vamos usar o “peso_a1_b2” para este exemplo.

Antes de mais nada, vamos relembrar todas as contas que fazemos para nossa rede neural. Para tal, eu vou usar a notação “peso_ax_by” para indicar o peso que sai do neurônio “ax” e vai para o neurônio “by”. Note que NÃO EXISTE “peso_a1_b1”, porque o neurônio “b1” é o “bias”, logo o valor dele é sempre “1” (e não faria sentido calcular um valor se ele vai descartá-lo e usar “1”, no fim das contas). Sabemos que o valor de um neurônio oculto é a soma de todos os valores dos neurônios de entrada (multiplicados por seus devidos pesos) e aplicadas uma “função de ativação” (que no nosso caso, é a “Tangente Hiperbólica”). Eu vou chamar de “b_sem_ativacao_x” o valor desta soma dos neurônios de entrada, ANTES de se aplicar a função de ativação. Logo, nossas contas são:

b\_antes\_ativacao\_2 = a1 * peso\_a1\_b2 + a2 * peso\_a2\_b2 + a3 * peso\_a3\_b2 \\  b\_antes\_ativacao\_3 = a1 * peso\_a1\_b3 + a2 * peso\_a2\_b3 + a3 * peso\_a3\_b3 \\  b\_antes\_ativacao\_4 = a1 * peso\_a1\_b4 + a2 * peso\_a2\_b4 + a3 * peso\_a3\_b4 \\  \\  b2 = tanh(b\_antes\_ativacao\_2) \\  b3 = tanh(b\_antes\_ativacao\_3) \\  b4 = tanh(b\_antes\_ativacao\_4) \\  \\  c1 = b1 * peso\_b1\_c1 + b2 * peso\_b2\_c1 + b3 * peso\_b3\_c1 + b4 * peso\_b4\_c1 \\  c2 = b1 * peso\_b1\_c2 + b2 * peso\_b2\_c2 + b3 * peso\_b3\_c2 + b4 * peso\_b4\_c2 \\  \\  custo = \frac{1}{2 * N} * \sum\limits_{n=1}^N \sum\limits_{i=1}^2 (ci(do\ exemplo\ n) - yi(do\ exemplo\ n)) ^ 2
(more…)

Redes Neurais – Parte 2

No post anterior, vimos como montar a estrutura de uma rede neural. Neste post, veremos como fazer o treinamento dos pesos, para que a rede generalize nossos exemplos de teste e seja capaz de classificar exemplos que ainda não foram vistos. Num primeiro momento, vamos relembrar o desenho de uma rede neural:

Neural

Para facilitar, deixei um nome para cada neurônio (nota: provavelmente vocês não vão encontrar essa forma de nomear os neurônios em lugar algum-eu coloquei essa nomenclatura mais para facilitar o post do que para ser uma abordagem matemática mesmo). Os neurônios “a1” e “b1” são “bias”, conforme vimos no post anterior, e os neurônios “c1” e “c2” são os neurônios de saída. Note que este desenho de rede neural não representa nossa rede neural, pois nossa rede neural precisaria de 5 neurônios de entrada e 3 de saída. Bom, conforme vimos no post anterior, num primeiro momento os pesos sinápticos (as linhas ligando os neurônios, representadas pelas matrizes “input_weights” e “hidden_weights” no post anterior) são aleatórios, o que significa que a rede possuirá comportamento aleatório. A partir deste ponto, temos que alterar os pesos para tentar chegar num resultado melhor da rede. Para tal, precisamos de uma função que nos mostre quão bom é a solução atual: uma “função de custo”.
(more…)

Redes Neurais For Dummies

Ultimamente, muito tem-se falado sobre “machine learning” e redes neurais, então resolvi tentar trazer à luz alguns conceitos que eu tenho aprendido e que tem pouca (ou nenhuma) informação fácil na internet. A primeira coisa a se pensar é que todo o conceito de Redes Neurais, SVM, e outras técnicas de Machine Learning são áreas da matemática, portanto tudo o que for processado numa Rede Neural tem que, de alguma forma, ser convertido para números (o que não é exatamente um problema na maioria dos casos).

As redes neurais podem ser usadas para prever determinados valores, mas são principalmente usadas no processo de classificação de algo (por exemplo, eu tenho um conjunto de sintomas e quero classificar esse conjunto em uma doença conhecida) ou clusterização/agrupamento de valores (da mesma forma, eu tenho um conjunto de características de um país e quero separá-lo em conjuntos). Existem vários modelos de redes neurais, e neste primeiro post vou falar da rede perceptron. Este post está dividido em duas partes, a primeira (este post) será a montagem de uma rede neural, e a segunda, será sobre o treinamento da rede.

Neural
(more…)

Usando a Tipagem de Scala para Validar Parâmetros

Bom, primeiramente, muita coisa aconteceu por isso a falta de postagens, mas espero que daqui pra frente seja possível postar mais coisas interessantes.

Esses dias, estou tentando encapsular um código Java em um código Scala, basicamente, um código de matrizes, multiplicação de matrizes, etc, e será este o exemplo que usarei neste post. Para os que não lembram de matrizes, as operações sobre matrizes devem seguir uma determinada regra, por exemplo, adição de matrizes só podem ser efetuadas quando as duas matrizes possuem mesmo número de elementos:

class Matrix(protected val list: List[List[Double]] {
  def +(other: Matrix) = new Matrix(list zip other.list map { case(me, other) =>
    me zip other map { case(e1, e2) => e1 + e2 }
  })
}

Para os que não conhecem tão bem Scala, o código a seguir soma uma matriz com a outra chamando o método zip, que basicamente, de posse de dois objetos que possam ser iterados (tipo um List), combinam seus elementos:

List(1, 2, 3) zip List(4, 5, 6)
=> List( (1, 4), (2, 5), (3, 6) )
List(List(1, 2)) zip List(List(3, 4))
=> List( (List(1, 2), List(3, 4)) )

O “case”, no map (e no foreach, e em qualquer closure) separa os dois elementos. Seria possível separar também com map { e => e._1, e._2 } mas fica um pouco mais feio o código.

Legal, o código acima funciona mas… ele permite somar matrizes de dimensões diferentes. Claramente, isso não é desejado. Podemos fazer o método nos retornar um erro quando tentarmos somar matrizes de dimensões diferentes:

  def +(other: Matrix) = {
    require(list.size == other.list.size, "Number of rows must be the same")
    require(list(0).size == other.list(0).size, "Number of cols must be the same")

    new Matrix(list zip other.list map { case(me, other) =>
      me zip other map { case(e1, e2) => e1 + e2 }
    })
  }

Ou podemos usar a tipagem para isto.
(more…)

Scala, Traversable, e Implicits

Meu primeiro post bem técnico sobre Scala, vamos ver no que dá (rs).

Bom, primeiro, um pouco de “background”: comecei o fantástico curso de Machine Learning no site coursera.org, e todas as lições que estão no site são em Octave/Matlab. Não conhecia Octave, muito menos Matlab, e quando programei nestas linguagens descobri algumas coisas meio estranhas (bom, eu pelo menos considero estranho que, ao esquecer de colocar um “;” no final de um comando, ele imprima o resultado na tela), além, claro, de não ser possível programar pra Android, por exemplo.

Como estou estudando Scala, e como já consegui fazer Scala rodar no Android de um jeito menos “doloroso” (mais sobre isso em outro post), resolvi fazer os códigos em Scala. Há bibliotecas boas de multiplicação de matrizes em Scala, porém comparadas com as versões Java, elas são BEM mais lentas. Foi aí que pensei: por que não encapsular uma dessas bibliotecas Java em Scala?

Tudo correu bem, até o momento que resolvi que queria que cada matriz funcionasse como um Traversable. Para quem é de Ruby, o Traversable é equivalente ao Enumerable, com algumas coisas a menos e outras a mais. Só para comparar, vamos ver o código dos dois (para simplificar, vou omitir alguns códigos, mas a API é a seguinte: Matrix#rows e Matrix#cols para saber o número de linhas e colunas, Matrix#* multiplica matrizes ou uma matriz com um número. Também, a matriz possui um atributo, “list”, que contém um array de arrays com os elementos internos da matriz).

class Matrix(list: List[List[Double]]) extends Traversable[Double] {
  def cols = 3 //Só pro nossos códigos de exemplo compilarem...
  def foreach[B](function: Double => B) = list.flatten.foreach { e => function(e) }
}
class Matrix
  include Enumerable
  def each(&b)
    list.flatten.each &b
  end
end

Repare que o código é semelhante nas duas linguagens, a diferença básica é que em Ruby não precisamos definir tipos, em Scala precisamos (não que nesse caso faça alguma diferença). Só que temos um caso engraçado tanto em Ruby como em Scala: se queremos um método que, digamos, eleve todos os elementos ao quadrado, elemento por elemento, ao usar “map” para fazer esse processo, ele vai nos retornar, em Ruby, um Array, e em Scala, um Traversable[Double]. E pior, os elementos vão ficar “achatados”. Em ambos, é possível resolver isso fazendo o “each” (ou o “foreach”) retornar uma lista de elementos que está em cada linha, mas ainda assim temos o problema que nosso retorno será semelhante a um “array de arrays”, não uma matriz. O que fazer?

Bom, em Ruby, a gente se ferrou, literalmente. Não temos uma maneira de fazer isso que não envolva sobrescrever o map, e todos os métodos que constrõem uma lista a partir de outra. Em Scala, temos “implicits”, e um conceito “canBuildFrom”.
(more…)

Extraindo o Máximo do Android

Bom, estes dias comprei um Android, um Samsung Galaxy S2, e como todo bom usuário de Linux, já fiz algumas modificações no sistema. A coisa que achei mais diferente é a dificuldade de achar informações sobre como fazer as alterações, tal como “root” ou instalações de ROMs customizadas. Então, resolvi postar aqui como fazer estas alterações.

Em primeiro lugar, vale mencionar algumas coisas sobre o Android. Como todo Linux, ele possui um “kernel” separado do sistema. Além disso, o Android é dividido em um sistema base que fica montado em “/system”, e uma área para os dados dos aplicativos (possível de ser escrita pelo usuário) montado em “/sdcard”. No meu caso, ainda, ele possui um cartão SD externo, que fica montado em “/sdcard/external_sd”. Além disso há uma sopa de letras tipo “FactoryFS”, “Modem”, “Secondary Kernel” e outras coisas que eu entendo só por cima.

Para adquirir acesso “root”, há várias formas diferentes. Uma delas consiste em instalar um kernel diferente, mas aí você ganha um triângulo amarelo no seu celular quando você vai iniciá-lo, então todo mundo fica sabendo que você fez uma modificação. A outra, consiste em instalar um sistema de arquivos diferente. Basicamente o processo é fazer um “flash” no celular, com um kernel modificado (no primeiro caso) ou com um sistema modificado (no segundo). Para o Linux, uso o software “heimdall” (http://www.glassechidna.com.au/products/heimdall/). A versão 1.3.2 me deu problemas, então instalei a 1.3.1 e passei ao processo de flash. Eu recomendo o segundo método, pois o triângulo amarelo não fica presente, e basicamente consiste em baixar esta imagem: http://brasildroid.com.br/galaxy-s-ii-i9100-geral/6187-tutorial-root-ics-firmware-claro-tim-vivo-and-unbranded-oi.html. Depois, basta descompactá-la (usando zip ou rar), e você vai ter um arquivo .tar.md5 ou um arquivo .tar. Para descompactar esse arquivo, basta usar “tar -xf arquivo”, e finalmente a imagem está pronta para o processo de flash.

O processo de flash é bem simples, mas antes de fazê-lo, lembre-se de algumas coisas: primeiro, o suporte técnico da Samsung VAI encher o saco se descobrir que você fez uma modificação dessas no celular, e você pode perder a garantia. Segundo, faça o processo, de preferencia, de um notebook, e SEMPRE com o celular com bateria cheia ou quase cheia-não queremos que ausência de energia (tanto do PC como do celular) estraguem o processo todo, certo?

Então, para fazer o flash, basta deixar o celular num modo específico (modo de download) desligando-o e segurando “power+home+abaixar volume”. Ele pedirá uma confirmação, basta confirmar com o “aumentar volume”, e usar o heimdall. Eu rodei-o com o comando:

sudo heimdall flash --primary-boot boot.bin --cache cache.rfs --dbdata dbdata.rfs --factoryfs factoryfs.rfs  --modem modem.bin --param param.lfs --secondary-boot Sbl.bin --kernel zImage

Caso algum problema aconteça, não se desespere-basta tirar a bateria do celular e colocá-la novamente, e de novo deixa o celular em modo de “download” com a sequencia acima.

Enfim, com esse passo, seu celular terá acesso “root” e coisas interessantes podem ser instaladas (rastreadores que ligam automaticamente o GPS, por exemplo, ou o “Scala Installer” que pré-instala Scala no seu android e permite programar em Scala ao invés de Java, sem o processo de build demorado do proguard… mas mais sobre isso num outro post). Mas, se você quer algo mais hardcore, talvez seria interessante testar o CyanogenMod
(more…)

Android x iOS

Bom, comprei um android, depois da quebra do meu iPhone. Com três semanas de uso, acho que é interessante mencionar uma comparação dos dois, tentando ser o mais imparcial o possível.

Adiantando, eu estou gostando mais do android-mesmo reconhecendo que há pontos muito superiores no iPhone. Como forma de comparação, vou usar equipamentos com preços semelhantes (no caso, o aparelho android que tenho é um Samsung Galaxy S2). Termos como “o iPhone usa melhor o hardware porque um iPhone de 800mhz é comparável a um Android 1.2ghz” não fazem sentido aqui-de que adianta o processador ser mais fraco se, no fim, o preço do aparelho é o mesmo?

Enfim, começando pelo ponto mais positivo do Android-nada de iTunes. Sorry, folks, mas sinceramente o iTunes me lembra o Adobe Acrobat PDF Reader-um software que deveria fazer algo relativamente simples, e é pesado, lento, precisa de diversas atualizações (uma mais pesada que a outra) e necessita de uma super máquina pra rodar. Além disso, a idéia de “sincronizar músicas” do iTunes é uma porcaria-afinal, se eu tenho dois computadores, eu só posso sincronizar de um, caso contrário tenho que deletar TODA a minha playlist e começar de novo… não sei se no iTunes novo isto está corrigido (porque, como usuário de Linux, eu não usava o iTunes quase nunca).
(more…)

Ensaio Sobre a Violência – Dois

Bom, antes de voltar ao ritmo habitual do site, talvez seja interessante mencionar algo que há algum tempo tem me incomodado (e mais ainda agora, já que sofri um assalto que me deixou bem assustado com algumas coisas, mas enfim).

A violência encanta. Não adianta tentar dizer o contrário, ela está em novelas, em filmes, em praticamente qualquer obra de ação que olhemos. Ela encanta de tal forma que nos acostumamos com ela, que “é normal” ouvir um tiroteio de vez em quando, que “não sei quem foi assaltado, colocaram uma arma na cabeça dele”, e outras histórias que são ditas e repetidas pelas mais diversas pessoas, e que todos acabam ouvindo eventualmente numa conversa de ônibus, numa pessoa falando muito alto no celular, ou algo semelhante.

Exceto que não deveria ser deste jeito.

Quando as coisas acontecem com você, parece que alguma coisa muda. Olhando bem, você fica imaginando-se, naquela situação, relembrando os atos, sendo deixado sozinho no meio de uma rodovia, sem documento nenhum, sem absolutamente nenhuma forma de comunicação, e fica dependente da bondade de estranhos que também têm medo de serem assaltados e provavelmente não vão confiar em alguém pedindo ajuda à noite numa rodovia, certo? E depois desta tortura, a segunda tortura que é ligar para a polícia, através de um telefone emprestado de alguém, pedindo ajuda e esperar, e esperar, e esperar, até finalmente se tocar que a viatura que eles disseram que iam mandar pra te ajudar não vai chegar. E então você consegue uma carona de uma alma bondosa que não vai aparecer em jornal algum embora merecesse uma grande recompensa, vai até uma delegacia, e lá começa a retratar e reviver o que aconteceu para um escrivão que te olha com cara de “por que você está aqui me fazendo perder meu tempo”, até o momento em que você se sente não a vítima, mas o culpado. E de repente, finalmente um estalo no seu cérebro que lhe diz que não, não vai adiantar nada chamar a polícia e que você só está fazendo boletim de ocorrência por causa do seguro… e você percebe que aqueles que lhe assaltaram vão ficar impunes, e que provavelmente a punição deles virá no dia em que assaltarem a pessoa errada, que provavelmente vai estar armada e vai reagir… mas isso, se acontecer, vai demorar ainda, e enquanto isso você vai voltar pra casa, tirar todos os seus documentos de novo, comprar um novo veículo e sair de casa com medo de ser assaltado de novo…

É… pessoalmente, a violência não tem NADA de encantadora.
(more…)