Hatena::ブログ(Diary)

今日のひとこと このページをアンテナに追加 RSSフィード Twitter

FessプロジェクトS2Robotプロジェクトで開発したい人を募集中

2012年03月10日

[]ブログ移転 21:37 ブログの移転を含むブックマーク ブログの移転のブックマークコメント

結構、ここのブログも長い間使ってきましたが、別にここでなくても良いかなっと思い始めていたので、以下に移転しました。

http://www.chazine.com/

最近、あんまりブログを書く時間もなくなっている気もしますが、もうちょっとがんばって書いていこうかと思います。ではでは。

2012年02月13日

[]codehausmojoコミッターになりました 22:40 codehausのmojoコミッターになりましたを含むブックマーク codehausのmojoコミッターになりましたのブックマークコメント

このブログもほとんど書けない感じで残念な感じですが、久々に書いておきます。codehausコミッターには別になるつもりはなかったのですが、話の流れでなぜかmojoコミッターになりました。今までどこかのプロジェクトコミッターになるときは、結構、あれこれ作業する感じなのですけど、今回は対象のプロジェクトの引き取り手がいないから誰かいない?みたいな今までにない感じの流れです。そんな感じで、今までにない感じ受けたので、やっていかねばなりません。引き受けたプロジェクトはjspcのMavenプラグインです。個人的には大規模なサイトとかでは有用プロダクトな感じもするのですけどね。まぁ、地道にいじっていきたいとは思っているので、何かありましたらお知らせください。

http://mojo.codehaus.org/jspc-maven-plugin/

コミット権限はもらったものの、まだ試せていないので、まずはコミット確認を試さないと…。

2011年12月23日

[]Fess 5.0 リリース 08:17 Fess 5.0 リリースを含むブックマーク Fess 5.0 リリースのブックマークコメント

最近、書く時間がなくて、このブログ放置気味な感じですけど…。そんな感じですが、先週、Fess 5 をリリースしましたFess 5では

という感じで新機能的な感じは少ないですけど、まぁ、機能的には(たぶん)十分に揃っているかと。以下で入手可能です。

http://sourceforge.jp/projects/fess/releases/

次の Fess 5.1 はUIの変更やlucene-gosenを統合したりとか、細々としたことを入れてリリースしたいと考えています。まぁ、もしかしたら、バージョンは 5.5 とかにするかもしれないけど。

あとは、今週、第7回 Solr検索エンジン勉強会で話した資料は以下に置いておきました。

http://www.slideshare.net/shinsuke/solr-fess

という感じで、どんどん使ってくださいー。

2011年08月06日

[][]人工データを作る 22:41 人工データを作るを含むブックマーク 人工データを作るのブックマークコメント

Mahoutというか,その中にはそれっぽいライブラリが見つからなかったのだけど,科学技術計算実験系で人工データを作りたいときに困ったので作ってみた

import java.io.Serializable;
import java.util.Random;

import org.apache.mahout.math.DenseVector;
import org.apache.mahout.math.Vector;

public class SyntheticDataGenerator implements Serializable {
	private static final long serialVersionUID = 1L;
	private Random[] randoms;
	private double[] means;
	private double[] stdevs;

	public SyntheticDataGenerator(long seed) {
		means = new double[1];
		means[0] = 0;
		stdevs = new double[1];
		stdevs[0] = 1;
		init(seed, 1, means, stdevs);
	}

	public SyntheticDataGenerator(long seed, int cardinality, double[] means,
			double[] stdevs) {
		init(seed, cardinality, means, stdevs);
	}

	private void init(long seed, int cardinality, double[] means,
			double[] stdevs) {
		if (cardinality != means.length || cardinality != stdevs.length) {
			throw new IllegalArgumentException("Invalid cardinality.");
		}
		randoms = new Random[cardinality];
		for (int i = 0; i < cardinality; i++) {
			randoms[i] = new Random(seed + i);
		}
		this.means = means;
		this.stdevs = stdevs;
	}

	public double nextDouble() {
		return nextDouble(0);
	}

	protected double nextDouble(int i) {
		return randoms[i].nextGaussian() * stdevs[i] + means[i];
	}

	public double[] nextDoubles() {
		double[] values = new double[randoms.length];
		for (int i = 0; i < randoms.length; i++) {
			values[i] = nextDouble(i);
		}
		return values;
	}

	public Vector nextVector() {
		return new DenseVector(nextDoubles());
	}
}

1次元正規分布に基づく人工データを作りたいときには以下な感じ.

double[] means = new double[1];
double[] stdevs = new double[1];
means[0] = 10; // 平均 10
stdevs[0] = 5; // 標準偏差 5
SyntheticDataGenerator generator = new SyntheticDataGenerator(0, 1, means, stdevs);

あとは,generator.nextDouble() で値を取得していくと指定した分布乱数が取得できる.そんで,多次元データが欲しい場合は,各次元ごとのmeansとstdevsを配列に格納して,generator.nextDoubles() としてやれば配列がとれるし,nextVector()でMahoutVectorとして取得できる.

2011年07月24日

[]Fess 4.1.0リリース 20:42 Fess 4.1.0リリースを含むブックマーク Fess 4.1.0リリースのブックマークコメント

4.0.0から半年以上経過してしまいましたが,ようやく4.1.0をリリースしました.新機能の追加というよりバグなどの対応が主になるかと思います.まぁ,バグと言ってもFess自体のはあまりなくて,Tikaとか,PDFBoxとか,HttpClientとか利用しているものたちに起因するものがほとんどかと思います.そういうこともあって,ここまで来るのに時間がかかった気もします.一応,新機能的なところとしては,Solrの持つファセットも利用できるようになりました.という感じで,4.x系はバグ対応的なリリースしか今後はせずに,基本は5.x系に注力していく予定です.っで,次のFess 5.0では,Tomcat 7とSolr 3.2の採用を考えています.これらがさくっとできれば,すぐに5.0がリリースされると思いますし,そうでなければちょっと時間がかかるかも.そんな感じですが,引き続きよろしくお願いしますー.

http://fess.sourceforge.jp/ja/

2011年07月09日

[]Vectorは良いのか? 16:21 Vectorは良いのか?を含むブックマーク Vectorは良いのか?のブックマークコメント

気になるので,Vectorを使う場合とプリミティブな配列で処理したときパフォーマンス影響を確認してみる.たぶん,Vectorで利用される実装はDenseVectorとRandomAccessSparseVectorあたりな気がするので,これらと比較する.DenseVectorは内部的にはプリミティブ配列と同様に全次元数分の容量を確保する(内部的にはdouble配列だし).RandomAccessSparseVectorは必要な要素だけを確保する(簡単に言うと内部的にはMapみみたいなイメージだと思う).単純に以下のコード比較してみた.

	public void test_performance() {

		int count = 100;
		int dim = .../*次元数*/;
		int testNum = .../*利用した要素数*/;
		testDenseVector(count, dim, testNum);
		sleep(5000);
		testSparseVector(count, dim, testNum);
		sleep(5000);
		testArrayVector(count, dim, testNum);
		sleep(5000);

		testDenseVector(count, dim, testNum);
		sleep(5000);
		testSparseVector(count, dim, testNum);
		sleep(5000);
		testArrayVector(count, dim, testNum);

	}

	private void testArrayVector(int count, int dim, int testNum) {
		long time = System.currentTimeMillis();
		long oldHeapSize = getHeapSize();
		double[][] data = new double[count][];
		for (int i = 0; i < count; i++) {
			data[i] = new double[dim];
			for (int j = 0; j < testNum; j++) {
				data[i][j] = j;
			}
		}
		long heapSize = getHeapSize();
		System.out.println("array vector: "
				+ (System.currentTimeMillis() - time) + "ms, " + heapSize
				+ "MB(" + (heapSize - oldHeapSize) + "MB)");
		for (int i = 0; i < count; i++) {
			for (int j = 0; j < testNum; j++) {
				data[i][j] = j;
			}
		}
	}

	private void testDenseVector(int count, int dim, int testNum) {
		long time = System.currentTimeMillis();
		long oldHeapSize = getHeapSize();
		DenseVector[] vectors = new DenseVector[count];
		for (int i = 0; i < count; i++) {
			vectors[i] = new DenseVector(dim);
			for (int j = 0; j < testNum; j++) {
				vectors[i].setQuick(j, j);
			}
		}
		long heapSize = getHeapSize();
		System.out.println("dense vector: "
				+ (System.currentTimeMillis() - time) + "ms, " + heapSize
				+ "MB(" + (heapSize - oldHeapSize) + "MB)");
		for (int i = 0; i < count; i++) {
			for (int j = 0; j < testNum; j++) {
				vectors[i].setQuick(j, j);
			}
		}

	}

	private void testSparseVector(int count, int dim, int testNum) {
		long time = System.currentTimeMillis();
		long oldHeapSize = getHeapSize();
		RandomAccessSparseVector[] vectors = new RandomAccessSparseVector[count];
		for (int i = 0; i < count; i++) {
			vectors[i] = new RandomAccessSparseVector(dim);
			for (int j = 0; j < testNum; j++) {
				vectors[i].setQuick(j, j);
			}
		}
		long heapSize = getHeapSize();
		System.out.println("sparse vector: "
				+ (System.currentTimeMillis() - time) + "ms, " + heapSize
				+ "MB(" + (heapSize - oldHeapSize) + "MB)");
		for (int i = 0; i < count; i++) {
			for (int j = 0; j < testNum; j++) {
				vectors[i].setQuick(j, j);
			}
		}
	}

	private long getHeapSize() {
		final Runtime runtime = Runtime.getRuntime();
		return (runtime.totalMemory() - runtime.freeMemory()) / 1000000;
	}

	private void sleep(long time) {
		System.gc();
		try {
			Thread.sleep(time);
		} catch (InterruptedException e) {
		}
	}

GCとかの都合とかもあってスリープとかもろもろ入れておく.

まず,100,000次元10,000要素を使った場合

dense vector: 103ms, 80MB(80MB)
sparse vector: 133ms, 37MB(37MB)
array vector: 92ms, 80MB(80MB)

次に,100,000次元20,000要素を使った場合

dense vector: 113ms, 80MB(80MB)
sparse vector: 237ms, 67MB(67MB)
array vector: 99ms, 80MB(80MB)

さらに,要素数を25,000にすると

dense vector: 114ms, 80MB(80MB)
sparse vector: 388ms, 110MB(110MB)
array vector: 108ms, 80MB(80MB)

最後に100,000要素を利用すると

dense vector: 130ms, 80MB(80MB)
sparse vector: 1469ms, 376MB(376MB)
array vector: 110ms, 80MB(80MB)

という感じだった.

というわけで,メモリ的には,次元数の20%以下の利用で済むのであれば,RandomAccessSparseVectorで,それ以上ならDenseVectorが良いかな(時間的なことを考えると,10%くらいでもよいのかも).プリミティブ配列とDenseVectorに大きな差はないけど,若干早いような感じかね.プリミティブ配列で処理するかは,10%の速度向上をとるか,利便性をとるかのどちらが必要かを考えて判断するべきかね.

2011年07月08日

[]Tasteについて思うこと 09:11 Tasteについて思うことを含むブックマーク Tasteについて思うことのブックマークコメント

ここ数カ月くらい、研究実験MahoutのTasteを結構使ってみました。個人的な感想ですが、フレームワークとしては使えるけど、富豪(?)でない人が利用するのは厳しい気がしました。ここでいう富豪とは最新のPCを数十や数百台とか使って問題解決できる人のことを指してます。最新のPCを数台とかで計算するようなときにはTasteの中身の実装は非効率と感じています(富豪でもコストパフォーマンスを気にする人は微妙かもな)。機械学習みたいな、科学技術計算的な問題を解こうとすると、基本は激しいループ処理なのでその中でnew 〜とかでインスタンスを作ったり、インスタンス配列やListやMapなどで何かしだすと終わりません…。MahoutVectorベクトル計算するには便利なのですけど、富豪でないとちょっと厳しい気がしてきていますJavaだと、インスタンスの破棄をGCに期待することになり、メモリは消費されるし、GCスレッドも負荷が高くなるし、とかなりやられました(パラレルGCCMSG1とかも試したけど、CMSが一番良かった気がする)。そんなわけで、始めはTasteに乗っかって作っていましたが、最終的にはインターフェースは同じ感じだけど、中身の実装は作りこんでいった感じ(Mahoutが実装したKDDCupDataModelだと10G以上のメモリが必要っぽいけど,実装しなおすと6Gくらいでさくっと扱えるようになったりします)。改善して行った点は、インスタンスの生成やListとかMapの利用とかもできる限りやめて、基本はプリミティブな値やその配列とかでやる感じにしました(Javaっぽくないけど)。そんな感じの改善をしていくことで、数十〜数百倍くらいのパフォーマンス改善できた気がしてます。というわけで、富豪でない私みたいな人用に、プリミティブな配列とかでベクトル行列計算ができるようなものを作る必要があるのかな、と考え始めてます…。

2011年05月27日

[]混合多項分布 10:44 混合多項分布を含むブックマーク 混合多項分布のブックマークコメント

私自身の混合多項分布の理解度はまだいまいちな気もするけど、とりあえず、ここにあったPythonコードJavaで書き直してみた。

public class MultinomialMixture {
	double[][] dataset;
	int num;
	int dim;
	int mNum;
	double[][] c;
	double[][] q;

	public MultinomialMixture(double[][] dataset, int k) {
		this.dataset = dataset;
		num = dataset.length;
		dim = dataset[0].length;
		mNum = k;
		q = new double[mNum][dim];
		c = new double[num][mNum];

		Random random = new Random(1);
		for (int i = 0; i < mNum; i++) {
			for (int j = 0; j < dim; j++) {
				q[i][j] = random.nextDouble();
			}
			q[i] = normalize(q[i]);
		}
	}

	public void execute(int loop) {
		for (int i = 0; i < loop; i++) {
			stepE();
			stepM();
		}
	}

	double[] normalize(double[] value) {
		double[] ret = new double[value.length];
		double sum = 0;
		for (int i = 0; i < value.length; i++) {
			sum += value[i];
		}
		for (int i = 0; i < value.length; i++) {
			ret[i] = value[i] / sum;
		}
		return ret;
	}

	double multi(double[] u, double[] x) {
		//    return prod([q[w] ** d[w] for w in range(W)])
		double value = 1;
		for (int i = 0; i < u.length; i++) {
			value *= Math.pow(u[i], x[i]);
		}
		return value;
	}

	void stepE() {
		//	    for n in range(N):
		//       C[n] = normalize([multi(D[n], Q[k]) for k in range(K)])
		for (int i = 0; i < num; i++) {
			double[] dn = dataset[i];
			for (int j = 0; j < mNum; j++) {
				c[i][j] = multi(q[j], dn);
			}
			c[i] = normalize(c[i]);
		}
	}

	void stepM() {
		//	    for k in range(K):
		//	        Q[k] = normalize([sum([C[n][k] * D[n][w] for n in range(N)]) for w in range(W)])
		for (int i = 0; i < mNum; i++) {
			double[] value = new double[dim];
			for (int j = 0; j < dim; j++) {
				value[j] = 0;
				for (int k = 0; k < num; k++) {
					value[j] += c[k][i] * dataset[k][j];
				}
			}
			value = normalize(value);
			q[i] = value;
		}
	}

	double logLikelihood() {
		//	    L = 0
		//	    for n in range(N):
		//	        p = [C[n][k] * multinomial(D[n], Q[k]) for k in range(K)]
		//	        L += log(sum(p))
		double l = 0;
		for (int i = 0; i < num; i++) {
			double sum = 0;
			for (int j = 0; j < mNum; j++) {
				sum += c[i][j] * multinomial(dataset[i], q[j]);
			}
			l += Math.log(sum);
		}
		return l;
	}

	double multinomial(double[] d, double[] q) {
		//	    return factorial(sum(d)) / prod([factorial(d[w]) for w in range(W)]) * multi(d,q)
		double prod = 1;
		for (int i = 0; i < dim; i++) {
			prod *= factorial(d[i]);
		}
		return factorial(sum(d)) / prod * multi(q, d);
	}

	double factorial(double x) {
		//	    if x == 0: return 1
		//	    return reduce(mul, xrange(1, x+1))
		double prod = 1;
		for (int i = 1; i < x + 1; i++) {
			prod *= i;
		}
		return prod;
	}

	double sum(double[] v) {
		double sum = 0;
		for (int i = 0; i < v.length; i++) {
			sum += v[i];
		}
		return sum;
	}

	public void print() {
		System.out.println("L=" + logLikelihood());

		//		c = new double[num][mNum];
		StringBuilder buf = new StringBuilder();
		buf.append("C=[");
		for (int i = 0; i < num; i++) {
			buf.append('[');
			for (int j = 0; j < mNum; j++) {
				buf.append(c[i][j]);
				if (j != mNum - 1) {
					buf.append(',');
				}
			}
			buf.append(']');
			if (i != num - 1) {
				buf.append(',');
			}
		}
		buf.append(']');
		System.out.println(buf.toString());

		//		q = new double[mNum][dim];
		buf = new StringBuilder();
		buf.append("Q=[");
		for (int i = 0; i < mNum; i++) {
			buf.append('[');
			for (int j = 0; j < dim; j++) {
				buf.append(q[i][j]);
				if (j != dim - 1) {
					buf.append(',');
				}
			}
			buf.append(']');
			if (i != mNum - 1) {
				buf.append(',');
			}
		}
		buf.append(']');
		System.out.println(buf.toString());
	}
}

使うときは以下の感じ。

		int k = 2;
		MultinomialMixture mm = new MultinomialMixture(dataset, k);
		mm.execute(10);
		mm.print();

かなり勢いで書いたから、細かいことは後で直すとして、Pythonのやつと同じ感じの結果だったからとりあえず、よしとする。

2011年05月21日

[][]pdfbox 1.5 で扱えるpdfエンコーディング 15:11 pdfbox 1.5 で扱えるpdfのエンコーディングを含むブックマーク pdfbox 1.5 で扱えるpdfのエンコーディングのブックマークコメント

pdfエンコーディングにもいくつかあるけど、ネットから拾い集めてテキスト抽出できるか試してみた。

  • Identity-H → OK
  • 90ms-RKSJ-H → OK
  • 90pv-RKSJ-H → OK
  • 83pv-RKSJ-H → NG

というわけで、pdfboxで83pv-RKSJ-Hのpdfからテキスト文字列抽出すると文字化けする。はて、Fessではどうしようかな・・・。

2011年04月10日

[]学生になりました 21:20 学生になりましたを含むブックマーク 学生になりましたのブックマークコメント

最近,このブログ更新放置気味ですが,今月から九州大学大学院システム情報科学研究情報学専攻の社会人博士課程に入学しました.そんなわけで,10年ぶりくらいに学生です(学割が使えるのかしら…).大学に戻って何がしたいかというと,機械学習データマイニングを再度勉強しようかと思っています.そんでもって,その知識を使って利益を上げていく仕組みを作るっていうあたりが目指すところかと(なので,何か仕事があればください).福岡にもこの前,初めて行ったくらいな感じで,近頃の大学事情とかもよくわかっていなかったりするので,学生の方々にはいろいろと教えてもらえると嬉しいなとか思っています.そんな感じで,がんばっていきたいと思いますのでよろしくおねがいしますー.