<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="../../../../../css/rss/feedRss2.xsl" media="screen" type="text/xsl"?>

<rss version="2.0"> 
  <channel> 
    <title>JAVAでデータマイング！</title>  
    <link>http://ameblo.jp/th0083/</link>  
    <description>『情報工学の難しいそうなアルゴリズムをJAVAで実装して、ひたすらその結果を公開する』ブログになる予定。</description>  
    <language>ja</language>  
    <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="self" href="http://feedblog.ameba.jp/rss/ameblo/th0083/rss20.xml" type="application/rss+xml"/>  
    <item> 
      <title>当たり前ですけど、学習データって大事です。</title>  
      <description><![CDATA[<p>
 最近仕事で spam 判別器なんての作成していたんですが、この spam の分類器を作成していて思ったことがあります。<br />
<br />

<br />
自分も割とそうなのですが、いわゆる精度を上げるために、アルゴリズムに傾倒してしまうようなことが普通にあって、<br />

<br />

<br />

ベイズがベイジアンネットになり、SVMになり、ＳＶＭ＋カーネルロジスティックのBoostingになり・・・って具合でどんどん難しいアカデミックなところを攻めてしまうわけですが、<br />

<br />

<br />

しかしながら実際の所、純粋に精度を上げるためには、<br />
<br />
<br />
実はアルゴリズム云々よりも、<br />

<br />

<br />

学習データの作りかたの方がよほど大事なんじゃないかなぁ？ってのが、最近の私の感想です。<br />

<br />

<br />

この前、2値問題のスパム判定やってたんですが、<br />

<br />

<br />

久々に学習データを見直すって話で、学習データ数を３倍に上げて、変数選択を見直したら検出数が二倍になり、<br />

<br />

<br />

更にスパムを５カテゴリくらいに分割して、カテゴリ毎の学習データをそれぞれ作って、どれかスパムカテゴリに入ったらアウト！みたいな判定したら、検出数が３倍になったとかありました。<br />

（無論精度は担保してあります。）<br />

<br />

<br />
まぁ、元々のベースが酷すぎるだろ！？って話は、あるんですけど、<br />
<br />

<br />

想定するspamの言語空間(spamの定義) と 学習データとの誤差を無くすってのが、いかに大事かってことを身にしみて思った次第です。<br />

<br />

<br />

単純な エロspamコメント っていっても、実はサービスによって、その表現方法は微妙に異なります。<br />
<br />
<br />
一例を上げると、サービスのキャリア、つまりＰＣ or 携帯向けのサービスっていう所でも、画面表示力の差で携帯の方が短文スパムが送られてくる比率が非常に高い。<br />
<br />
<br />
他にも、メッセージの種類、サービス利用者の層、認証のあるなし、などといったところで、やはりそれぞれに微妙に差異があるわけです。<br />
<br />
<br />
その差異って実は決定的だったりするんですね。<br />
<br />
<br />
また単純にspam判定されたテキストをそのまま学習データにしていくと、誤差がどうしても生まれるという話もあります。<br />
<br />
<br />
例えば、一文中にspamだと思われる部分が８割あったとして、残りの２割は普通の文面だったとすると、後者の２割が、結構悪戯するわけです。<br />
<br />
<br />
具体的には、外れ値除去とか変数選択とか、ホント真面目にやれって話なんですけどね。<br />
<br />
<br />
まぁ、というわけで、<br />
<br />
<br />
サービスごとのspamの傾向をうまく学習データに反映させたり、学習データの誤差を取り除くってのは凄く大事って話で、<br />
<br />
<br />
確かにアルゴリズムをSVMにするってのは、普通というか、大事なことだとは思うんですけど、<br />
<br />
<br />
それと同じかそれ以上に、学習データの作り方が、あたり前ですけど、改めて大事だなぁっと思った次第です。<br />
<br />
<br />
終り。<br />
<br />
<br />
<br />

<br />

<br />
 
</p>]]></description>  
      <link>http://ameblo.jp/th0083/entry-10392171809.html</link>  
      <pubDate>Thu, 19 Nov 2009 20:57:19 +0900</pubDate> 
    </item>  
    <item> 
      <title>Naive Bayes　その一 - smoothing -</title>  
      <description> <![CDATA[ 　テキストマイニングをやっていると、初期の頃は Naive Bayes とか使うと思うのですが、<br />


<br />


<br />


まぁベイズの定理とかしばらく眺めてると、それなりに誰でも分かると思うんです。<br />


<br />


<br />


一応オサライだけしとくと、<br />


<br />


<br />




<table cellpadding="10" border="1"><tbody><tr><td>ベイズの定理<br />


　　　　事後確率 = （　事前分布　×　尤度　） /  結果<br />


</td>


</tr>


</tbody>


</table>


<br />


<br />


で、実際に式書くとこんな感じ。<br />


<br />


<br />




<table cellpadding="10" border="1"><tbody><tr><td><br />


p( c | x ) = p( c ) Π_i p( w_i | c ) / p( x )<br />


<br />


( x = { w_1　・・・　w_N }   )<br />


</td>


</tr>


</tbody>


</table>


<br />


<br />


<br />


でした。<br />


<br />


<br />


classification する際には、『結果』 p( x ) は c ごとの p( c | x ) を比較する上では無用なので、<br />


<br />


<br />


結局、『尤度』 p( x | c ) と 『事前分布』 p( c ) の積が大事なんだよーって話でした。<br />


（　実装ではちゃんと両者にlogとって足し算にしてください！でないと桁あふれするから！　）<br />


<br />


<br />


で、<br />


<br />


<br />


この次の話としては、p( w_i | c )の解釈って実は２パターンあって、<br />


<br />


<br />


それぞれ Multinomial NaiveBayes とか、Bernoulli NaiveBayes っていうんだよという話がでてくる。<br />


<br />


<br />


この辺りで、もう簡単なspam filter の実装ができるくらいになっていて、なんだ簡単じゃんと思っていたところに、Smoothingの話がでてくる―――<br />


<br />


<br />


―――んだが、しかし、<br />


<br />


<br />


普通に Smoothing でググると、N-gram言語モデルの資料とかが出てきて？？？になり、<br />


<br />


<br />


うまい資料とかがなくて、なんだかヤサグレテきて、<br />

<br />

<br />

とりあえずWEBに出てきたラプラススムーシング辺り使っとけばいいじゃん？<br />


<br />


<br />


ってなことをして、精度劣化しまくりで、なんだこれ？？？ってパターンになったりするんですな。<br />


<br />


<br />


というというわけで！（前振り長！！）<br />


<br />


<br />


今日はNaive Bayes　の Smoothing の話をしてみます！<br />


（　結論からいうと、<a href="http://www.lr.pi.titech.ac.jp/~takamura/pubs/notesNB.pdf">この辺</a>


みれば全部載ってる！ｗ　　）<br />


<br />


<br />


<br />


<br />


閑話休題。<br />


<br />


<br />


<br />


Smoothingってのは、<br />


<br />


<br />


ある特定のクラスCの学習データに存在していない 単語ｗ　がクエリに存在した場合、<br />
( 他のクラスでは w は学習データに登場している )<br />


<br />


<br />


p( w | c ) = 0 なので、<br />


<br />


<br />


事後確率 p( c | x ) ∝　P ( c ) Π_i P( w_i | c ) <br />


<br />


<br />


において、事後確率が0になってしまう。つまり、クエリテキストがどんなにクラス c らしい単語を沢山所持していても w を含むだけでそのテキストは c に属することができなくなる―――<br />


<br />


<br />


―――んだけど、それは直感的にまずいですね？さぁどうしよう？？<br />
<br />
<br />
という時に使われるヒューリスティックルールのことです。<br />

（正確にはベイズ確率の事前分布の話から来ているんだけど）<br />


<br />


<br />


具体的にどうするかというと、<br />
<br />
<br />
基本的には、全ての単語に非常に小さな確率の下駄を履かせておいて p( w_i | c ) をゼロにならなくなるようにするのです。<br />


<br />


<br />


一応有名ところを挙げておくと、<br />


<br />


<br />


n( w | c )    クラス c の学習データに登場する単語 w の数<br />


δ              smoothing parameter<br />


| V |           辞書単語の総数<br />


| W( c ) |     クラス c に登場する単語の種類数  <br />


<br />


<br />


として、<br />


<br />


<br />


<font size="4" style="font-weight: bold;">○Additive Smoothing( 加算スムーシング )</font><br />




<table cellpadding="10" border="1"><tbody><tr><td><br />


p( C | w ) =  { δ + n( w | C ) } / δ|V| + Σ_i n( w_i | C )<br />


<br />


</td>


</tr>


</tbody>


</table>


<br />


<br />


<font size="4" style="font-weight: bold;">○Laplace Smoothing</font><br />




<table cellpadding="10" border="1"><tbody><tr><td><br />


p( C | w ) =  { 1 + n( w | C ) } / |V| + Σ_i n( w_i | C )<br />


<br />


</td>


</tr>


</tbody>


</table>


<br />


<font size="4" style="font-weight: bold;"><br />


○Backoff Smoothing </font><br />




<table cellpadding="10" border="1"><tbody><tr><td><br />


p( C | w ) = <font size="2"> ( n( w | C ) - δ) / Σ_i  n( w_i | C )                             if n( w_i ,C )  &gt; 0</font><br />


　　　　　　<font size="1">&nbsp;</font>=  <font size="2">( δ | W(C) | ) / ( | W( C ) | - | V | ) * Σ_i  n( w_i | C )    if n( w_i ,C )  = 0</font><br />


<br />


</td>


</tr>


</tbody>


</table>


<br />


<br />


<font size="4" style="font-weight: bold;">○Interpolation Smoothing( 補完スムーシング )</font><br />




<table cellpadding="10" border="1"><tbody><tr><td><br />


p( C | w ) =  <font size="2">max { 0 ,   ( n( w | C ) - δ) / Σ_i  n( w_i | C )  }  </font><br />


             +  <font size="2">( δ | W(C) | ) *  Σ_c  n( w_i | C ) /   { Σ_i  n( w_i | C ) *   Σ_c Σ_i  n( w_i | C )  }</font><br />


<br />


</td>


</tr>


</tbody>


</table>


<br />


<br />


<br />


こんなのがあります。<br />


<br />


<br />


Laplace Smoothingとかがよく？webで紹介されてる気がするんだけど、<br />


<br />


<br />


ホントダメだから絶対に使わない方がいい。<br />


<br />


<br />


これは私的感覚だけど、補完スムーシングが一番精度が良いと思う。私ぁいつもこれ使ってる。<br />


<br />


<br />


さて、<br />


<br />


<br />


ここで一つ老婆心ながら注意？しときたいがあるんです・・・、おそらく。<br />


<br />


<br />


『　smoothingの仕方で精度が変わるのか？　』<br />


<br />


<br />


これって、きっと誰でも気になったりすると思うのですが、<br />


（　昔の人もそう思ったらしくて論文とかあるけどね　）<br />


<br />


<br />


まぁ私的な結論としては、Naive Bayes に関していうと、<br />


<br />


<br />


<font size="4" style="font-weight: bold;">まぁ別に変わんないんじゃないの？</font><br />


<br />


<br />


って思ってます。<br />


（　補完スムーシングがいいって・・・さっきと言ってることが違う・・・ってのは置いておいて　）<br />


<br />


<br />


確かにδ値が大きいうちはスムーシングによって判別器の性質って違うような気がするのですが、<br />


<br />


<br />


大体どのスムーシングも、δの値を調整（大抵は凄く小さい値）にしてけば、多値問題だろうが、ニ値問題だろうが判別結果はほぼ同じになります。<br />


<br />


<br />


まぁデータや変数の取り扱いがいい加減な時はいざ知らず、データの外れ値除去をちゃんとやって、変数（単語）選択をちゃんとやれば、スムーシングはどれでやってもほぼ同じってのが私の感覚です。<br />


<br />


<br />


というわけで、<br />


<br />


<br />


パラメータ調整とか新たなスムーシングの実装に腐心するよりも、<br />


<br />


<br />


ＳＶＭの勉強とか、Logistic regressionの実装した方が、時間は有益に使えるんじゃないかなぁ？<br />


<br />


<br />


と個人的には思ってますマス。<br />


<br />


<br />


はい。<br />


<br />


<br />


そんなことに時間をかけてた私は、、、、<br />


<br />


<br />


昔は私も青かったなぁ・・・なんて。。。<br />


<br />


<br />


おわり。<br />
]]> </description>  
      <link>http://ameblo.jp/th0083/entry-10354407558.html</link>  
      <pubDate>Thu, 01 Oct 2009 00:36:51 +0900</pubDate> 
    </item>  
    <item> 
      <title>LSH その4　－pstableのサンプルコード－</title>  
      <description> <![CDATA[ 休み中にLSHの実装を見直しました。<br />



<br />



<br />



pstableの実装が、かなり雑だったのでパッケージの構造から大幅に改修しました。まだまだですね。。。<br />



<br />



<br />



せっかくなのでp-stableのサンプルコード的なモノ(Mavenのテストコード)を書いてみました。<br />



（以前書いた<a href="http://ameblo.jp/th0083/entry-10272072125.html">simHashのテストコード</a>



も訂正しておきました。）<br />



<br />



<br />






<div style="border: 1px solid rgb(51, 51, 51); padding: 5px;"><br />



package jp.ndca.toolkit.cluster.lsh.hash.pstable.data;<br />



<br />



import static org.junit.Assert.assertEquals;<br />



<br />



import java.io.BufferedReader;<br />



import java.io.IOException;<br />



import java.io.InputStream;<br />



import java.io.InputStreamReader;<br />



import java.util.ArrayList;<br />



import java.util.List;<br />



import java.util.Properties;<br />



<br />



import org.junit.Test;<br />



<br />



import jp.ndca.toolkit.cluster.lsh.hash.HashProbability;<br />



import jp.ndca.toolkit.cluster.lsh.hash.pstable.NormalHashFunctionHandler;<br />



import jp.ndca.toolkit.cluster.lsh.hash.pstable.NormalHashProbability;<br />



import jp.ndca.toolkit.cluster.lsh.hash.pstable.PstableHandler;<br />



import jp.ndca.toolkit.cluster.lsh.hash.pstable.PstableHandlerWrapper;<br />



import jp.ndca.toolkit.cluster.lsh.hash.pstable.data.PstableHammingDataStore;<br />



<br />



public class PstableDataHammingStoreTest {<br />



    <br />



    　　@Test<br />



    　　public void testSearch() throws IOException{<br />



        <br />



　　　　/**<br />



      　　　　* ベクトルデータの読み込み<br />



      　　　　*/<br />
　　　　InputStream is <br />



　　　　　　= Thread.currentThread().getContextClassLoader().getResourceAsStream(&quot;lsh.txt&quot;);<br />



      　　　　BufferedReader br = new BufferedReader( new InputStreamReader(is) );<br />



        <br />



      　　　　List&lt;int[]&gt; vectorList = new ArrayList&lt;int[]&gt;();<br />



        <br />



　　　　while( br.ready() ){<br />

　　　　　　String line = br.readLine();<br />



                     　　　　　　line = line.substring(1);                  　　　　　　　　　　//[を除去<br />



                     　　　　　　line = line.substring(0, line.length()-1);  //]を除去<br />



          　　　　　　String[] numbers = line.split(&quot;,&quot;);<br />



                     　　　　　　if(numbers.length != 0)<br />



                             　　　　　　　　vectorList.add( StringArrayToIntegerArray(numbers) );<br />



             　　　　}<br />



        <br />



      　　　　/**<br />



      　　　　* LSHパラメータの取得<br />



      　　　　*/<br />



      　　　　Properties prop = new Properties();<br />



　　　　InputStream _is <br />



　　　　　　= Thread.currentThread().getContextClassLoader().getResourceAsStream(&quot;lsh.properties&quot;)<br />



      　　　　prop.load( _is );<br />



<br />



　　　　double c = Double.valueOf(prop.getProperty(&quot;c&quot;));<br />



　　　　double r = Double.valueOf(prop.getProperty(&quot;r&quot;));<br />



            <br />



　　　　HashProbability pp = new NormalHashProbability( c, r );<br />



      　　　　double p1 = pp.getGoodHashProb();<br />



             　　　　double p2 = pp.getBadHashProb();<br />



<br />



　　　　int n = Integer.parseInt(prop.getProperty(&quot;n&quot;));<br />



      　　　　int dimension = Integer.parseInt(prop.getProperty(&quot;dimension&quot;));<br />



        <br />



　　　　PstableHandler ph = new NormalHashFunctionHandler( p1, p2, n, dimension, r );<br />



        <br />



      　　　　int K = ph.getK();<br />



             　　　　int L = ph.getL();<br />



        <br />



      　　　　/**<br />



　　　　* 検索データの変換<br />



      　　　　*/<br />



      　　　　PstableHandlerWrapper phw <br />



                     　　　　　　= new PstableHandlerWrapper( ph.generateHashFunctionVectorGeneratorList( K, L ) );<br />



      　　　　PstableHammingDataStore pstableDataHammingStore <br />



          　　　　　　= new PstableHammingDataStore( vectorList, phw );<br />



        <br />



　　　　/**<br />



      　　　　* 検索の実行<br />



　　　　*/<br />



             　　　　int[] query = new int[]{  1 , 105, 119, 152, 177, 196, 215, 258, 315, 343, 413, 448 };<br />



<br />



　　　　long start = System.currentTimeMillis();<br />



　　　　String[] pstableHashes =  phw.getPstableHashes(query);<br />



             　　　　int[] result = pstableDataHammingStore.search(pstableHashes);<br />



　　　　long end = System.currentTimeMillis();<br />



             　　　　long diff = end - start;<br />



        <br />



　　　　assertEquals( true, classify(result, 9) );<br />



      　　　　System.out.println(vectorList.size());<br />



      　　　　System.out.println(result.length);<br />



             　　　　System.out.println( diff );<br />



        <br />



　　}<br />



    <br />



　　private static int[] StringArrayToIntegerArray( String[] array ){<br />



      　　　　int[] intArray = new int[ array.length ];<br />



　　　　for( int i = 0 ; i &lt; array.length ; i++){<br />



　　　　　　if(array[i].equals(&quot;&quot;))<br />



			　　　　　　　　continue;<br />



	 　　　　　　intArray[i] = Integer.parseInt( array[i].trim() );<br />



　　　　}<br />



      　　　　return intArray;<br />



　　}<br />



    <br />



　　private static boolean classify( int[] candidateIds, int id ){<br />



            　　　　for( int candidateId : candidateIds){<br />



                    　　　　　　if(candidateId==id)<br />



　　　　　　　　return true;<br />



                　　　　}<br />



　　　　return false;<br />



        　　}<br />



<br />



}<br />



</div>



<br />



<br />



このテストクラスでやってるのは、<br />



<br />



<br />



①　lsh.txtのHammingデータをint[]で取得した後、<br />



②　クラスパス直下にあるlsh.propertiesでpstableに必要なパラメータを読み込み、<br />



③　このパラメータから、理論に用いる中間パラメータを生成。<br />



④　②、③のパラメータをPstableHandlerに渡して、LSHのデータ変換行列を作成。<br />



⑤　この後、PstableHammingDataStoreにて、ハッシュ値と、idを格納するmap&lt;String, List&lt;Integer&gt;&gt;を内部的に生成し、<br />



⑥　最終的に、int[] queryで検索を行い、近傍点を抽出する。<br />



<br />



<br />



ということをしています。<br />



<br />



<br />



ちなみにこのqueryは、検索対象の lsh.txt の中にある10行目（ ID9番目 ） のHammingデータと1成分しか違わないデータです。<br />


<br />


<br />


テストコードでは、これがＩＤ9番目のハッシュ値と一緒になるということをclassifyメソッドで確かめています。<br />



<br />



<br />



実際にテストコードを動かせばわかるとは思うのですが、このコードの計算時間は1ms以下であり、近傍データの候補として、全１０００件のデータの中から大体50程度の近傍データの候補を抽出してきます。<br />



<br />



<br />



queryに対して、普通に全てのデータとのユークリッド距離を計算しようとすると、たとえ今回のテストケースのように検索対象データが1000件程度であっても数十msかかってしまうので、それに比べたらかなり高速だという話です。<br />



<br />



<br />



良かったら、何かに使ってくださいまし。<br />



<br />



<br />



ちなみにこの検索では、LSHの検索条件 （ 2L個の候補データの抽出によって探索を打ち切る等 ） によって探索を終了するなどということは行っていません。あしからず。<br />



<br />



<br />



ではでは。<br />



<br />



<br />



<br />
]]> </description>  
      <link>http://ameblo.jp/th0083/entry-10284514382.html</link>  
      <pubDate>Sun, 21 Jun 2009 02:33:48 +0900</pubDate> 
    </item>  
    <item> 
      <title>階層的クラスタリング　その2　 －サンプルコード－</title>  
      <description> <![CDATA[ 前回公開した階層的クラスタリングの<a href="http://code.google.com/p/hierarchiccluster/source/browse/">ライブラリ</a>


 を使ったサンプルコードを書いて見ました。<br />





<br />





<br />





よくある色のデンドグラムを作成するテストコードです。<br />





<br />





<br />





こんな感じ。<br />




<br />





<br />










<div style="border: 1px solid rgb(51, 51, 51); padding: 5px;"><br />





package jp.ndca.toolkit.cluster.hierarchiccluster.builder;<br />





<br />





import java.awt.Color;<br />





import java.util.ArrayList;<br />





import java.util.List;<br />





<br />





import jp.ndca.toolkit.cluster.hierarchiccluster.node.Member;<br />





import jp.ndca.toolkit.cluster.hierarchiccluster.node.Node;<br />





import jp.ndca.toolkit.cluster.hierarchiccluster.node.distance.impl.WardDistanceMeasure;<br />





import jp.ndca.toolkit.cluster.hierarchiccluster.vector.SparseVector;<br />





import jp.ndca.toolkit.cluster.hierarchiccluster.vector.distance.impl.EuclideanDistanceMeasure;<br />





import jp.ndca.toolkit.cluster.hierarchiccluster.view.TreeDisplaySupport;<br />





<br />





public class ClusterBuilderTest {<br />





<br />





　　public static void main(String[] args){<br />





<br />





        　　　　List&lt;Node&gt; nodes = new ArrayList&lt;Node&gt;();<br />





        <br />





                　　　　nodes.add( new Member( 0, colorToVector(Color.BLUE)) );<br />





        　　　　nodes.add( new Member( 1, colorToVector(Color.MAGENTA)) );<br />





        　　　　nodes.add( new Member( 2, colorToVector(Color.CYAN)) );<br />





        　　　　nodes.add( new Member( 3, colorToVector(Color.ORANGE)) );<br />





        　　　　nodes.add( new Member( 4, colorToVector(Color.PINK)) );<br />





        　　　　nodes.add( new Member( 5, colorToVector(Color.RED)) );<br />





        <br />





　　　　ClusterBuilder builder = new ClusterBuilder(<br />





                                    　　　　　　　　　　　　　　　　　　　　　new WardDistanceMeasure(<br />





                                        　　　　　　　　　　　　　　　　　　　　　　　new EuclideanDistanceMeasure() ));<br />





　　　　Node rootNode = builder.build(nodes);<br />





        　　　　TreeDisplaySupport tree = new TreeDisplaySupport();<br />





        　　　　tree.makeTreeDiagram(rootNode);<br />





<br />





    　　}<br />





    <br />





    　　private static SparseVector colorToVector(Color color){<br />





　　　　SparseVector resultVector = new SparseVector();<br />





　　　　resultVector.setQuick( 0, color.getRed() );<br />





　　　　resultVector.setQuick( 1, color.getGreen() );<br />





　　　　resultVector.setQuick( 2, color.getBlue() );<br />





　　　　return resultVector;<br />





    　　}<br />





<br />





}<br />





<br />





</div>





<br />





<br />





結果は、きっとこんな感じ。<br />





<br />





<br />










<div style="border: 1px solid rgb(51, 51, 51); padding: 5px;"><br />





+<br />





　　+<br />





　　　　5 (RED)<br />





　　　　+<br />





　　　　　　4 (PINK)<br />





　　　　　　3 (ORANGE)<br />





　　+<br />





　　　　2　（CYAN）<br />





　　　　+ <br />





　　　　　　1　（MAGENDA）<br />





　　　　　　0　（BLUE）<br />





<br />





</div>





<br />





<br />





と、<br />





<br />





<br />





ここまで書いて、実は肝心のデンドグラムの実装が追加されていないことに気がつきました。<br />





<br />





<br />





さっさと、その辺も追加せねば・・・。<br />



<br />



<br />



<br />



<br />



閑話休題。<br />



<br />



<br />



<br />



<br />



階層的クラスタリングは、情報の可視化という点で割りと便利なのですが、<br />



<br />



<br />



一方、ボトルネックとしては、計算量が O(n^3) であるということが挙げられます。<br />



（イメージ的には5千件程度を超えるともはや使い物にならない感じです。）<br />



<br />



<br />



一応、キャッシュありの実装で O( n^2 * ln(n) )　の計算アルゴリズムにはなるのですが、それでも計算量が O ( n^2 )　よりでかいので、実データを素直にクラスタリングすることは殆ど不可能です。<br />



<br />



<br />



これを回避する手段としては<br />



<br />



<br />



はじめにK-meansなどで事前のクラスタリングを行い、その結果（クラスタ中心）を、階層的クラスタリングで処理させるとかいう手法が最もポピュラーです。<br />



（データマイナー屋さんとかは特にこれをやります）<br />



<br />



<br />



他の回避手法としては、<a href="http://sd.is.uec.ac.jp/research/pdf/2003CVIM-141-57.pdf">LSH( bit sampling )と連帯して計算量を削減するというような話</a>

もあるのですが、この辺のロジックがweb上のデータでも適用できるかはちょっと不明なので、そのうち自分で試してみたいとは思っています。<br />



<br />



<br />





ちなみに、計算時間の削減といえば、並列化→『map reduce』 とかいうような話も思い浮かぶかと思うのですが、<br />



<br />



<br />



階層的クラスタリングにおいては  『map reduce』 の登場機会は恐らくありません、<br />



<br />



<br />


というのは、<br />


<br />


<br />


まず、前提として O ( n^3 )  の実装であれば、問題なく普通の map reduce を行うことができ、インスタンスの数に比例して計算時間が減少するのですが、 <br />


<br />


<br />


O ( n^2 * ln (n) )　の実装では、メモリキャッシュを前提にするので(　メモリの代わりにDBとかでもいーのですがそれだとIOで劇遅くなります )、マルチインスタンス ( メモリ共有不可 ) のmap reduce への適用は不可能という事情があります。<br />



<br />



<br />


一方、実際の計算速度はというと、O( n^2 * ln (n) )　の実装は、O( n^3 ) より遥かに速い―――<br />


<br />


<br />


―――というわけで、『map reduce』 の意義が殆どないわけです。<br />



<br />



<br />



まぁいずれにしても、階層的クラスタリングを使う際は計算量がボトルネックになるので、直接的な使い方はまずできず、何かしかの工夫が必要になってきますよ。という話でした。<br />


<br />


<br />



おわり。<br />



<br />



<br />



<br />



<br />



<br />



<br />





<br />
]]> </description>  
      <link>http://ameblo.jp/th0083/entry-10277338246.html</link>  
      <pubDate>Tue, 09 Jun 2009 19:06:00 +0900</pubDate> 
    </item>  
    <item> 
      <title>階層的クラスタリング　その1　- ward法（キャッシュ有）の実装公開 -</title>  
      <description> <![CDATA[ 階層的クラスタリングのコードをJavaで書いて見ました。<br />








<br />








<br />








url ： <a href="http://code.google.com/p/hierarchiccluster/source/browse/#svn/trunk%3Fstate%3Dclosed">hierarchiccluster</a>








<br />








<tt id="checkoutcmd"><br />








svn : </tt><tt id="checkoutcmd">svn checkout <strong><em>http</em></strong>://hierarchiccluster.googlecode.com/svn/trunk/ hierarchiccluster-read-only</tt><br />








<br />








<br />








階層的クラスタリングのコード自体は、一応web上でもチラホラみかけるのですが、<br />








<br />








<br />








キャッシュ有りの実装とか、一番精度の良いウォード法のデンドグラムの書き方とか、そういう肝心の細かい部分が省略されているソースが多いので、その辺りをちゃんと書いた、ウォード法のキャッシュ有り実装を今回作ってみました。<br />








<br />








<br />








とはいえ、相変わらずエラーハンドリングとかほぼ皆無です。<br />







<br />







<br />





ちなみに正常動作確認は行いましたが（だったらtestコード書けとかいう話ですが、）、肝心の時間評価などは全くしてません―――<br />





<br />





<br />





―――が、多分キャッシュ無しよりはよっぽど早いはずです。<br />








<br />








<br />








良かったら使ってください。<br />








<br />








<br />




<br />




<br />




閑話休題。<br />




<br />




<br />




<br />








<br />




ちなみにこの実装は、以下の書籍の内容を参考にしてつくりました。<br />








<br />








<br />
















<dl><dt><a href="http://click.affiliate.ameba.jp/affiliate.do?affiliateId=6103019" alt0="BlogAffiliate" target="_blank" rel="nofollow">クラスター分析入門―ファジィクラスタリングの理論と応用/宮本 定明<br />








<img height="160" border="0" width="110" src="http://ecx.images-amazon.com/images/I/41QMM38Y4XL._SL160_.jpg" /></a>








</dt>








<dt>￥3,150</dt>








<dt>Amazon.co.jp</dt>








</dl>








<br />








この本は入門書として結構有名な本で、基本からクラスタリングを学びたい人には向いていると思います。<br />








（　と初心者の私がいってみる。）<br />








<br />








<br />








『集合知プログラミング』よりも、多少難しい理論的なことが書かれてる感じですが、あわせて読むと丁度いいのではないかと思います。<br />








<br />


<br />


ではでは。<br />
]]> </description>  
      <link>http://ameblo.jp/th0083/entry-10276664565.html</link>  
      <pubDate>Mon, 08 Jun 2009 18:17:31 +0900</pubDate> 
    </item>  
    <item> 
      <title>LSH　その3　- simHashの類似度と精度 -</title>  
      <description> <![CDATA[ LSHを使う上で気になる点の一つとして、精度（再現率）と類似度の関係があげられると思います。<br />





<br />











<br />











LSHは、Hash関数とアルゴリズムのロジックの力で確率的に似ているデータを高速に探し出すのですが、<br />





<br />





<br />





それはあくまで &quot; 確率的 &quot;な探索であって、元々似ているデータのうちいくつかは検索結果から漏れてしまいますし、そもそも似ていないデータはあまり引っかかりません。<br />










<br />










<br />





端的にいえば、『どの程度似ているデータがどの程度の検索から漏れてしまうのか』を予め知っておかないと、思わぬ落とし穴にはまることになりかねません。<br />





<br />











<br />











というわけで、<br />



<br />



<br />



ここでは、『どの程度似ている（類似度）と、どの程度漏れるのか（再現率）？』といった相関を、simHashを例にして説明したいと思います。<br />









<br />











<br />






simaHashは元データをHash関数でバイナリのビット列に変換した後に、クエリとのHamming距離を計算して、閾値以下のモノを近傍データ候補として返すのですが、<br />











<br />











<br />











このHamming距離を閾値を大きくとれば、LSHの精度（再現率）は全体的に上昇していきます。<br />











<br />











<br />











以下では、その様子を グラフ* にしてみました。<br />





<br />



（　*　グラフは、任意次元のデータをsimHashで64次元へ次元圧縮した場合の、Cosine類似度と再現率の相関の理論値をあらわしています。（縦軸は再現率。横軸がCosin類似度)　）<br />











<br />











<a href="http://stat.ameba.jp/user_images/20090603/21/th0083/ec/4d/p/o0672039010190969929.png"><img border="0" style="width: 524px; height: 304px;" alt="JAVAでデータマイング！-simHash再現率" src="http://stat.ameba.jp/user_images/20090603/21/th0083/ec/4d/p/o0672039010190969929.png" /></a>











<br />











<br />











<br />











グラフの見方としては、例えば青色の線は ( 0.9 , 0.75)　付近の点を通過していますが、<br />











<br />











<br />











これは 『Hamming距離の閾値を10にした場合、クエリに対してcosin類似度で0.9の類似性を持つデータは75%の確率でLSHの検索結果に含まれる』という意味になります。<br />











<br />











<br />











上記のグラフを見ると、閾値を大きくとればとるほど、グラフの関数が右にズレていき、データの漏れがなくなっていく様子が伺えます。<br />











<br />











<br />











閾値が32にもなると、類似度0.4程度のモノであってもほぼ100％の再現率でとれているので、単純に『閾値あげればいいや』ってことになりそうですが、実はそうでもありません。<br />











<br />











<br />











このように閾値を段々大きくしていくと、単純にLSHの検索ヒット数が増大するのですが、この中には類似データでないモノも含まれる場合もあるので、そもそもの”近傍探索”の意義がなくなってしまうのです。（適合率が下がるって話です。）<br />











<br />











<br />











また、LSHの検索結果の誤検索データを排するために、LSHの検索結果に再距離計算を課す場合があるのですが、もしそのような再計算を行う場合、LSHの検索結果の増加は、トータルの検索時間パフォーマンスを著しく低下させます。<br />











<br />











<br />











ですので、実装者は自身の目的に見合う精度と、閾値（計算時間）を適切に選ばなければなりません。<br />










<br />











<br />











私の経験値としては、近傍データ( cosin類似度 &gt; 0.9 )抽出を目的としてＬＳＨを使用する場合は、閾値15程度（64bitへの次元削減の場合）で十分高速な検索ができました。<br />











(LSHの結果を再計算するのを込みで、計算時間は全計算の100分の一以下。検索対象データは実テキストデータ)<br />











<br />











<br />











よかったら参考にしてみてください。<br />











<br />
]]> </description>  
      <link>http://ameblo.jp/th0083/entry-10273236771.html</link>  
      <pubDate>Wed, 03 Jun 2009 10:33:29 +0900</pubDate> 
    </item>  
    <item> 
      <title>LSH その2 -lshの実装公開とsimHashのサンプルコード-</title>  
      <description> <![CDATA[ 前回の<a href="http://www.slideshare.net/JavaDM/lsh-p-stable">レポ</a>




















をまとめる際に作ったLSH実装を公開してみました。<br />






















(　注意　：　Javaで書いてあります。　)<br />























<br />









<br />























url ： <a href="http://code.google.com/p/locality-sensitive-hashing-src/source/browse/">locality-sensitive-hashing-src</a>























<br />









<tt id="checkoutcmd"><br />









svn : svn checkout <strong><em>http</em></strong>://locality-sensitive-hashing-src.googlecode.com/svn/trunk/ locality-sensitive-hashing-src-read-only</tt><br />























<br />























<br />























上記には今のところ、p-stableとrandom projection(simHash)のclassicな実装が含まれています。<br />













<br />













<br />













具体的には、p-stableは<a href="http://www.cs.princeton.edu/courses/archive/spring05/cos598E/bib/p253-datar.pdf">Locality-Sensitive Hashing Scheme Based on p-Stable Distributions</a>






















を、simHashは<a href="http://www.cs.princeton.edu/courses/archive/spring04/cos598B/bib/CharikarEstim.pdf">Similarity Estimation Techniques from Rounding Algorithms</a>













 の論文をもとに作成しました。<br />























<br />























<br />























ちなみに、どちらもエラーハンドリングとか、コメントとか、ほぼ皆無ですが・・・序所に直しますのでご容赦ください。<br />























<br />























<br />











<br />











<br />











閑話休題。<br />











<br />











<br />











<br />











web上のデータを取り扱う場合は、類似度ベースのLSHの方が何かと使う場面が多いと思うのですが、<br />






















<br />






















<br />






















上記のライブラリを使った場合の、simHashのサンプルコードはこんな感じになると思います。<br />























<br />























<br />














































<div style="border: 1px solid rgb(51, 51, 51); padding: 5px;">package jp.ndca.toolkit.cluster.lsh.hash.simHash.data;<br />





<br />





import java.io.BufferedReader;<br />





import java.io.IOException;<br />





import java.io.InputStream;<br />





import java.io.InputStreamReader;<br />





import java.util.ArrayList;<br />





import java.util.HashMap;<br />





import java.util.List;<br />





import java.util.Map;<br />





<br />





import org.junit.Test;<br />





<br />





import jp.ndca.toolkit.cluster.lsh.hash.simHash.SimHashHandlerWrapperLong;<br />





<br />





public class SimHashedLongDataStoreTest {<br />





<br />




　　@Test<br />





    　　public void testSearchWithinThreshold() throws Exception{<br />





<br />




　　　　List&lt;Map&lt;Integer,Short&gt;&gt; vectorList = makeSortData();<br />





        <br />





        　　　　//検索対象データの元次元数<br />





        　　　　int demension = 500;<br />





<br />




　　　　//検索ベクトルデータをsimHashした後のlongデータ<br />





        　　　　long[] resultList = new long[ vectorList.size() ];<br />





<br />


<br />





        　　　　/**<br />





　　　　* simHashの実行<br />





　　　　*/<br />





        　　　　SimHashHandlerWrapperLong simHash = new SimHashHandlerWrapperLong( demension );<br />





        　　　　for( int i=0 ; i &lt; resultList.length ; i++ ){<br />





            　　　　　　Map&lt;Integer,Short&gt; vectorX = vectorList.get(i);<br />





            　　　　　　resultList[i] = simHash.getSimHashByLong( vectorX );<br />





        　　　　}<br />





        　　　　SimHashedLongDataStore data = new SimHashedLongDataStore(resultList);<br />





<br />


<br />




　　　　//テストクエリを作成<br />





        　　　　String[] strQuery <br />





　　　　　　= new String[]{ &quot;1&quot; , &quot;105&quot;, &quot;119&quot;, &quot;152&quot;, &quot;177&quot;, &quot;196&quot;, &quot;215&quot;, &quot;258&quot;, &quot;315&quot;, &quot;343&quot;, &quot;413&quot;, &quot;448&quot; };<br />





        　　　　long query = simHash.getSimHashByLong( StringArrayToIntegerArray(strQuery) );<br />





<br />


<br />




　　　　/**<br />





         　　　　*　検索<br />





　　　　*/<br />





        　　　　int threshold = 15;<br />





        　　　　long start = System.currentTimeMillis();<br />





        　　　　int[] candidateIds = data.searchWithinThreshold( query, threshold );<br />





        　　　　long end = System.currentTimeMillis();<br />





        　　　　long diff  = end - start;<br />





        <br />


<br />





        　　　　/**<br />





         　　　　* 結果の表示<br />




　　　　*/<br />





        　　　　System.out.println( candidateIds.length );<br />





        　　　　for(int candidate :candidateIds)<br />





            　　　　　　System.out.println(candidate);<br />





        　　　　System.out.println( diff + &quot;ms&quot; );<br />





        <br />





    　　}<br />





<br />





    <br />





    　　/**<br />




　　* 検索データを作成<br />





     　　* @return<br />





     　　* @throws IOException<br />





     　　*/<br />





    　　private List&lt;Map&lt;Integer,Short&gt;&gt; makeSortData() throws IOException{<br />




<br />




　　　　List&lt; Map&lt;Integer,Short&gt; &gt; vectorList = new ArrayList&lt; Map&lt;Integer,Short&gt; &gt;();<br />




<br />




　　　　InputStream is = <br />





            　　　　　　Thread.currentThread().getContextClassLoader().getResourceAsStream(&quot;lsh.txt&quot;);<br />





        　　　　BufferedReader br = new BufferedReader( new InputStreamReader( is ) );<br />
<br />




　　　　while( br.ready() ){<br />
　　　　　　String line = br.readLine();<br />





            　　　　　　line = line.substring(1);                  　　　　　　　　　　　　//[を除去<br />





            　　　　　　line = line.substring(0, line.length()-1); 　　//]を除去<br />





            　　　　　　String[] numbers = line.split(&quot;,&quot;);<br />





            　　　　　　if( numbers.length != 0 )<br />




　　　　　　　　vectorList.add( StringArrayToIntegerArray(numbers) );<br />





            　　　　}<br />





        　　　　return vectorList;<br />




<br />





    　　}<br />





    <br />





    <br />




　　/**<br />





     　　* Stringデータをベクトルデータに変換。<br />





     　　* @param array<br />





     　　* @return<br />




　　*/<br />





    　　private static Map&lt;Integer, Short&gt; StringArrayToIntegerArray( String[] array ){<br />




<br />




　　　　Map&lt;Integer, Short&gt; resultMap = new HashMap&lt;Integer, Short&gt;();    <br />





        　　　　for( int i = 0 ; i &lt; array.length ; i++){<br />





            　　　　　　Integer key  = null;<br />





            　　　　　　if(array[i].equals(&quot;&quot;))<br />




　　　　　　　　continue;<br />




　　　　　　key = Integer.parseInt( array[i].trim() );<br />





            　　　　　　short num = resultMap.get(key) == null ? 0 : (short)(resultMap.get(key));<br />





            　　　　　　resultMap.put(key, ++num);<br />




　　　　}<br />





        　　　　return resultMap;<br />




<br />




　　}<br />





<br />





}<br />























</div>




　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　（2009/06/23 修正）<br />























<br />























上記のテストコードでは、<br />























<br />























<br />






















①　500次元検索対象データ1000個 を、ハッシュ関数で、64次元(long型)に次元圧縮する。<br />






















②　queryとして、lsh.txtの10番目の要素( ID9番 )と1成分しか違わないstrQueryを用いる。<br />


③　次元圧縮データと、queryのXor から閾値以上のモノを取得して検索結果にする。<br />























<br />























<br />























というようなロジックを内部的には実行しています。<br />























<br />























<br />






















コードを実行すればわかりますが、計算結果（検索にヒットする数）は1つのみで、9番目のIDを見事に探索してくれます。<br />


<br />


<br />


<br />


閑話休題。<br />


<br />


<br />


<br />


IDE環境上での実行という観点から、今回①では 500次元→64次元 という変換をしていますが、<br />


<br />


<br />


ここが仮に 50万次元→64次元 と大胆に次元圧縮してもデータの圧縮前の距離構造は無事に保存されています。精度的に特に問題ありません。<br />























(念のためにcandidateIdsのデータを再距離計算して確認した方がいいと思いますが)<br />























<br />























<br />























実際元のデータ次元が55万、検索データ数100万という設定でサーバー上でテストをしたことがあるのですが、<br />


<br />


<br />


この際、ある1クエリに対して、100万レコードの中から cosin distance &gt; 0.8 以上のデータを検索するために必要な検索時間は、再距離計算込みで平均100ms以下でした。再計算無しなら、50ms程度。<br />























<br />























<br />























100万レコードを逐次計算すると、10sくらいかかるので、計算時間は1000分の一以下です。<br />























（無論OSの環境や、検索対象レコードの内容によって多少違うとは思うのですが、）<br />























<br />























<br />























ちなみに、この際の検索の再現率は90%前半でした。<br />























<br />























<br />























LSHでは、よく変換行列のデータが肥大化してメモリを圧迫するというようなことがありますが、55万次元程度(丁度nlpに使う辞書データの数程度)であれば、数百M程度納まりす。<br />





















<br />





















<br />





















nlpや、高速な準完全一致検索を行いたい場合などには、結構使えるのではないでしょうか？<br />























<br />























<br />
]]> </description>  
      <link>http://ameblo.jp/th0083/entry-10272072125.html</link>  
      <pubDate>Mon, 01 Jun 2009 13:20:49 +0900</pubDate> 
    </item>  
    <item> 
      <title>LSH その1 -LSHの種類-</title>  
      <description> <![CDATA[ LSH(Locality Sensitive Hashing)という情報検索アルゴリズムが昨今注目を浴びています。<br /><br /><br />『大規模データ』に対する『高速な』検索が売りで、応用例としては、レコメンドや画像検索、準完全一致検索などがあります。<br /><br /><br />おそらく<a href="http://www2007.org/papers/paper570.pdf">GoogleのNews Agrigationの論文</a>が世の中に出てから一気に注目度が上がってきたように思うのですが、<br /><br /><br />それ以降も、<br /><br /><br /><a href="http://www.atmarkit.co.jp/news/200812/01/rakuten.html">楽天がレコメンドで使っている</a>とか、<br />楽天のテクノロジーカンファレンス(2008)で発表されたLSHレコメンドの論文だとか、<br />WebDB press No49で紹介されていたとか、<br /><br /><br />いう感じで、<br /><br /><br />昨年末～年初にかけて定期的にネタが投下されたので、ここ最近、国内ではちょっとしたブーム？になっていたような気がします。<br /><br /><br />LSHというアルゴリズム自体は、<br /><br /><br />『ベクトル空間上の近傍データを同じハッシュ値に変換するようなHash関数を用いて、検索対象データを予めハッシュ化してＤＢ（メモリ）にいれておく』<br /><br /><br />ということをしていれば、<br /><br /><br />『検索時に、クエリを同じハッシュ関数でハッシュ化した後で、ＤＢの中の同じハッシュ値のみを検索すれば良い！』<br /><br /><br />『ハッシュ検索だけなら検索速度はＯ（1）で超高速』<br /><br /><br />というのが基本的なアイデアです―――<br /><br /><br />―――という説明がよくなされるのですが、このような説明がなされると、<br /><br /><br />そんな都合の良いハッシュ関数なんてうまく決められるのか？という疑問が、まず最初に湧いてくるんじゃーないでしょうか？<br /><br /><br />というわけで、ちょっとその辺の説明をここでしたいと思います。<br /><br /><br />まず前提として、LSHの種類自体は大きくわけると4つの種類あって、概ねこのLSHの種類ごとに、それぞれHash関数が定義されています。<br /><br /><br />以下にその4種類をあげてみます。<br />(歴史的にもこの順番。①が古い。)<br /><br /><br />①　bit samplimg<br />②　Min-wise Independent Permutation (MinHash)<br />③　Random Projection (SimHash)<br />④　P-stable<br /><br /><br />実はこれら4種類のLSHはそれぞれ特定の距離を元にして検索を行うアルゴリズムでして、<br /><br /><br />①→Hamming距離<br />②→Jaccard距離<br />③→Cosion距離<br />④→Lp距離　(例えば、Manhattan距離、Euclid距離 )<br /><br /><br />にそれぞれ対応しています。<br /><br /><br />この4種類を距離の種類をごとにカテゴライズすると、①④は非類似度、②③は類似度ベースのＬＳＨに分類できるのですが、<br /><br /><br />実は裏にある理論背景も、①④と②③とでは割と違っています。<br />（一応②③は①④の理論の特別な場合似すぎないと②③の原著者らはいっているのだけど、前者に比べて後者は条件がかなり緩んでいたりするので、私的には殆ど別モノだという気がしています。）<br /><br /><br />歴史的には、LSHは①を元にして発展したきたので、①を最初に理解すべきだとは思うのですが、前述の理由でいきなり②③だけ理解することもできます。<br /><br /><br />実際のサービスでの利用を考えてもると、GoogleのNewsAgregationは②を使っており、またはテキスト分類では③を使う例が多い。<br /><br /><br />やはり実データは疎なデータが殆どなので、類似度との相性がよく、非類似度LSHを使う場面は( 画像検索なので一部使われていますが )結構少ない気がします。<br />（これは私がWeb屋さんなので、というフィルターを通しての見方かもしれませんが。）<br /><br /><br />さてそれで、肝心の①～④の具体的なHash関数の定義の仕方ですが、<br /><br /><br />さすがにブログではちょっと説明しきれないので、比較的新しい③④についてレポート資料を作ってたので公開しておきます。<br /><br /><br /><a href="http://www.slideshare.net/JavaDM/lsh-pstable-1565961">LSHを用いた非類似度計算の精度検証</a><br />(全画面モードでみないと見難いです。)<br /><br /><br />ちなみにこれは社内向けに提出したレポートで、④については簡単な精度検証もしています。<br /><br /><br />理論等はまとめて第２章に一通り書いてありますので、はじめての方はこの辺を読むのが良いと思われます。<br /><br /><br />文面は・・・おそらくかなり硬いですが、原著論文読むよりは、わかりやすく(詳しく)書いているのでよかったら参考にしてください。<br /><br /><br />一応下記に、①～④の原著論文も掲載しておきます。<br />①　<a href="http://graphics.stanford.edu/courses/cs468-06-fall/Papers/06%20indyk%20motwani%20-%20stoc98.pdf">Approximate Nearest Neighbor: Towords Removing the Curse of Dimensionality</a><br />②　<a href="http://www.cs.princeton.edu/courses/archive/spr04/cos598B/bib/BroderCFM-minwise.pdf">Min-wise Independent Permutation<br /></a>③　<a href="http://www.cs.princeton.edu/courses/archive/spring04/cos598B/bib/CharikarEstim.pdf">Similarity Estimation Techniques from Rounding Algorithms</a><br />④　<a href="http://www.cs.princeton.edu/courses/archive/spring05/cos598E/bib/p253-datar.pdf">Locality-Sensitive Hashing Scheme Based on p-Stable Distributions</a><br /><br /><br />ではでは。<br />
]]> </description>  
      <link>http://ameblo.jp/th0083/entry-10269427807.html</link>  
      <pubDate>Thu, 28 May 2009 08:45:58 +0900</pubDate> 
    </item>  
    <item> 
      <title>はじめに。</title>  
      <description> <![CDATA[ このブログは――――<br />




<br />




<br />




とある会社の研究開発部門に飛ばされた ( 志願した ) 新卒2年目の人が、<br />






<br />






<br />






無謀にも情報工学の理論と、その実装に挑戦して、その結果を報告するブログ――――になる予定です。<br />






<br />






<br />






ちなみに主のスペックは、<br />






<br />






<br />






・　25歳 (2009年05月時点で)<br />




・　Web会社勤務。<br />





・　大学は物理系。<br />






・　はじめてのプログラミングは大学３年の時の授業。（課題を全て友人にやらせて単位を取得した）　<br />






・　Java暦一年。<br />






・　システム開発暦　3ヶ月<br />






<br />






＜持ってる資格＞<br />






・　基本情報処理技術者試験<br />






<br />






<br />





とまぁこんな感じ。<br />





<br />





<br />





ようするに、研究開発するには完全に素人というわけですね。<br />





<br />






<br />




というわけで、正直どこまでできるか謎ですが、<br />

<br />

<br />

できる限り不特定多数の皆さんに、実データへの応用など行ってみた結果など、有意義な情報を提供できればと思っています。<br />





<br />





<br />

それではお手柔らかにお願いします。<br />
<br />
<br />
ではでは。<br />
]]> </description>  
      <link>http://ameblo.jp/th0083/entry-10267591488.html</link>  
      <pubDate>Wed, 20 May 2009 09:52:19 +0900</pubDate> 
    </item> 
  </channel> 
</rss>
