Posts tagged: MeCab

C#でMeCabを用いてマルコフ連鎖

このエントリーをはてなブックマークに追加
はてなブックマーク - C#でMeCabを用いてマルコフ連鎖

C#からマルコフ連鎖で文章生成するサンプルが見当たらなかったから書いてみた。
稚拙だと思うのでよくないところを指摘してくれるとうれしいのですが・・・

button1やらtextBox1やらtextBox2やら設置してポンッと。


        [DllImport("libmecab.dll")]
        extern static IntPtr mecab_new2(string arg);
        [DllImport("libmecab.dll")]
        extern static IntPtr mecab_sparse_tostr(IntPtr m, string str);
        [DllImport("libmecab.dll")]
        extern static void mecab_destroy(IntPtr m);


       private void button1_Click(object sender, EventArgs e)
        {
            //分かち書きした個々の言葉を配列に格納
            string wakatiText = makeWakati(textBox1.Text);
            string[] Words = wakatiText.Split(" ".ToCharArray());

            if (Words.Length - 2 < 0)
            {
                textBox2.Text = "単語数が不足しています";
                return;
            }

            //マルコフテーブル作成
            string[,] table = makeMarkovTable(Words);


            StringBuilder result = new StringBuilder();
            int wordNum = 0;
            HashSet addword = new HashSet();
            Random rand = new Random();
            List hitNo = new List();

            string firstWord_1 = Words[0];
            string firstWord_2 = Words[1];
                
            //最初の2文節をあらかじめ追加
            result.Append(firstWord_1+firstWord_2);

            //マルコフテーブルより文章生成
            while (true)
            {
                hitNo.Clear();
                for (int j = 0; j < table.GetLength(0); j++)
                {
                    if (table[j, 0] == firstWord_1 && table[j, 1] == firstWord_2 
                        && !addword.Contains(j))
                    {
                        hitNo.Add(j);
                    }
                }

                wordNum = hitNo[rand.Next(hitNo.Count)];
                result.Append(table[wordNum, 2]);

                addword.Add(wordNum);

                firstWord_1 = firstWord_2;
                firstWord_2 = table[wordNum, 2];


                if (firstWord_2 == "\n")
                    break;

            }
            textBox2.Text = result.ToString();
        }
        //MeCab用いて分かち書きした文字列を返す
        private string makeWakati(string text)
        {
            string result = null;
            IntPtr mecab = mecab_new2("-O wakati");
            IntPtr s = mecab_sparse_tostr(mecab, text);

            result = Marshal.PtrToStringAnsi(s);
            mecab_destroy(mecab);            
            return result;
        }
        //単語の配列からマルコフテーブル作成して返す
        private string[,] makeMarkovTable(string[] text)
        {
            string[,] MarkovTable = new string;
            try
            {
                for (int i = 0; i < (text.Length); i++)
                {
                    if (i + 2 >= text.Length)
                    {
                        MarkovTable[i, 0] = text[i];
                    }
                    else
                    {
                        MarkovTable[i, 0] = text[i];
                        MarkovTable[i, 1] = text[i + 1];
                        MarkovTable[i, 2] = text[i + 2];
                    }
                    if (text[i + 2] == "\n")
                        break;
                }
            }
            catch
            {
                return null;
            }
            return MarkovTable;
        }

で、結果はこんな感じに。


反捕鯨団体シー・シェパードの元船長、ピーター・ベスーン容疑者(44)が、調査捕鯨船団の監視船「第2昭南丸」に侵入した事件で、海上保安庁は14日午前、ベスーン容疑者を艦船侵入容疑で東京地検に送検した。ベスーン容疑者の身柄は同日中に、東京・葛飾区の東京拘置所に移される。

反捕鯨団体シー・シェパードの元船長、ピーター・ベスーン容疑者(44)が、調査捕鯨船団の監視船「第2昭南丸」に侵入した。ベスーン容疑者を艦船侵入容疑で東京地検に送検した事件で、海上保安庁は14日午前、ベスーン容疑者の身柄は同日中に、東京・葛飾区の東京拘置所に移される。




多分、サンプル見るよりもマルコフ連鎖は何なのかを調べたほうが早いと思います。
実際、PHPやらPythonのばっかりでどういうアルゴリズムなのかが良く分からず戸惑いました。



分かち書きして文節ごと(?)に分けて、[接頭語前,接頭語後,接尾語]のテーブル作って
接頭語後と接尾語をキーにして\n出るまで延々とループさせてるだけです。



人工無能を作ろう~マルコフ連鎖(2接頭語と1接尾語の場合)がとても参考になりました。

人工無能を作ろう~マルコフ連鎖(2接頭語と1接尾語の場合)人工無能を作ろう~マルコフ連鎖(2接頭語と1接尾語の場合)

このエントリーをはてなブックマークに追加
はてなブックマーク - C#でMeCabを用いてマルコフ連鎖

C#からMeCabを用いて形態素解析とわかち書き

このエントリーをはてなブックマークに追加
はてなブックマーク - C#からMeCabを用いて形態素解析とわかち書き

DBに6万件の文章を形態素解析しつつマルコフ連鎖のためのテーブル作成中。
意外と時間がかかるのだが何かおかしいのだろうか。

ということでC#からMeCabを利用してみた。
Binary package for MS-Windowsをダウンロード&インストール。

インストールしたフォルダからlibmecab.dllを探す。
C#のプロジェクトの.exe出力先フォルダ(DebugとかRelease)にコピー。

以下コード。

        [DllImport("libmecab.dll")]
        extern static IntPtr mecab_new2(string arg);
        [DllImport("libmecab.dll")]
        extern static IntPtr mecab_sparse_tostr(IntPtr m, string str);
        [DllImport("libmecab.dll")]
        extern static void mecab_destroy(IntPtr m);

 private string makeWakati(string text)
        {
            string result = null;
            IntPtr mecab = mecab_new2("-O wakati");
            IntPtr s = mecab_sparse_tostr(mecab, text);
            result = Marshal.PtrToStringAnsi(s);
            mecab_destroy(mecab);
            return result;
        }
IntPtr mecab = mecab_new2(“”);とすれば普通に形態素解析して出力してくれる。

destroyする前に結果を受け取らないと文字化けするので注意。

textはshift_jisで渡す。

このエントリーをはてなブックマークに追加
はてなブックマーク - C#からMeCabを用いて形態素解析とわかち書き

Dansette