【R&D番外編】ヴァイオリンコンサートに行ってきました
今回は趣向をちょっと変えて休日の出来事について綴ります。
IT関係の話では無いのであしからず。
8/24(水)、戸塚駅すぐそばの戸塚区民文化センターの4階さくらプラザに
妻と一緒にヴァイオリンコンサートを聴きに行ってきました。
6曲&アンコールに応えて弾いて頂いた「愛の悲しみ」(Byフリッツ・クライスラー)
の合計7曲です。
僕はピアノが趣味(意外かもしれませんが…)なので週末はよく弾いているけれど
ヴァイオリンの演奏はオーケストラとか以外では初めて聞いたカモ!?
ヴァイオリンに造詣は無いけれど、素晴らしい音色でした。
興奮がさめなかったので帰宅後にヴィヴァルディの夏をピアノで演奏しました。
妻からは「比較するの悪いけど演奏会より数ランク下がるね」と言われた…
当たり前だろうに(怒)
自分の娘が70人の前でヴァイオリンやピアノを演奏している姿を見たら僕は間違いなく泣くな…
とても有意義な休日でした。
今回、演奏してくれたヴァイオリニストのページをのせます。
奏でる音色がとても素敵なので興味のある方は是非ともこちらのページも参照下さい。
(御本人ではありませんが御家族の方の了解は得ました)
Sotaデビュー戦…
本日、台風の影響で採用説明会が中止となってしまい就職活動生に対して
デモをしようとしていたデビュー戦が延期となってしまいました。
音声加工やらで結構苦労していたのに文字通り水を注された格好になってしまった…
その代わりではないけれど、事業部長以上の役職者へのお披露目を行いました。
その際に気付いた事として「背後からの音声は認識しにくい(しない!?)…」
「α」「β」を分岐条件にしていたけれど、背後からいくら言っても微動だにしない!?
確かにテストの時には正面からしか「α」「β」と言わなかったのでちょっとびっくりです。
Sota君も心なしか少し落ち込んでいる…
音声で条件分岐させる場合には正面からだけではなく側面や背後からもテストをする様に
しましょう。いつも必ず正面から声を掛けられるとは限らないので…
なんちゃって音声認識サーバを作ろう
前の記事で音声認識を行う環境はできましたが、このままでは音声認識を使いたくなった場合に、その都度音声認識環境を構築しなければなりません。
それじゃああまりオシャレじゃないので、音声認識サーバを構築して各クライアントから利用できるようにします。
たったひとつの冴えたやりかた
音声認識サービスを構築するにあたって、いくつかの手段が考えられます。
- Juliusとは別にwebサービスを作成し、標準入出力等を利用してJuliusの機能を利用する。
- JuliusのAPIを組み込んだwebサービスを作成する。
- Juliusの入出力をネットワーク対応させる。
う~ん、どれもそれなりに面倒くさそう。
もう少し、何か手がないか考えてみよう。
終りなき戦い
Juliusのマニュアルを(今更ながら)熟読してみると、何やら興味深い記述に遭遇。
モジュールモード?何々。ネットワーク経由で音声認識結果を取得できます?
おおっ!正にお誂え向きの機能じゃないか!しかも動作確認のためのjcontrol.exeというツールまで用意されている。
説明を元にJuliusの起動バッチを作り、
.\bin\windows\julius.exe -C main.jconf -C am-gmm.jconf -demo -charconv utf-8 sjis -module
ついでにjcontrolの起動バッチも作って、
.\bin\windows\jcontrol.exe 127.0.0.1
ファイアウォールに穴もあけ、さーて準備OK。
両方のバッチを実行するとDOS窓が二つ開き、どうやら無事起動されたよう。
定番のセリフ「こんにちは」と話しかけると、xml形式で品詞とか発音情報とか信頼度スコアとかが表示されました。
<RECOGOUT>
<SHYPO RANK="1" SCORE="-2727.876221">
<WHYPO WORD="" CLASSID="<s>" PHONE="silB" CM="0.655"/>
<WHYPO WORD="こんにちは" CLASSID="こんにちは+感動詞" PHONE="k o N n i ch i w a" CM="0.424"/>
<WHYPO WORD="。" CLASSID="</s>" PHONE="silE" CM="1.000"/>
</SHYPO>
</RECOGOUT>
続けて「マイクテスト」としゃべったら、
<RECOGOUT>
<SHYPO RANK="1" SCORE="-2757.415039">
<WHYPO WORD="" CLASSID="<s>" PHONE="silB" CM="0.655"/>
<WHYPO WORD="バイク" CLASSID="バイク+名詞" PHONE="b a i k u" CM="0.097"/>
<WHYPO WORD="テスト" CLASSID="テスト+名詞" PHONE="t e s u t o" CM="0.120"/>
<WHYPO WORD="。" CLASSID="</s>" PHONE="silE" CM="1.000"/>
</SHYPO>
</RECOGOUT>
なるほど。単語ごとに結果が返されるのね(マイクがバイクとなったのはご愛敬)。
中々良いではないですか。では、本格的にクライアント機能を作ってみましょう。
(3分経過)
ところでプロトコルはどうなってるの?音声データはどうやって渡すの?
マニュアルを眺めてみたけどどうもよくわからない(実は重大な勘違いをしていたのですが、この時点では気づかず)。
せっかくのオープンソースですから、jcontrolのソースを見てみましょう。
う~ん。やっぱり音声データの受け渡しがされていないみたい。
(2時間ほど経過)
あっ!音声認識結果を取得できる!?
もしかして結果だけがネットワーク経由で受信できるってこと?
今一つ使い道がわかりませんが、どうやらそうゆうことのようです。
Oh my god!!! 振り出しにもどっちゃいました。
Juliusはそのままではサービス化できないのか?
やっぱり手ごろなクラウドサービスを使ったほうがいいのか?
自分で音声認識サービスを作ろうなどとは、見果てぬ夢だったのか?
あきらめきれずにマニュアルを眺めていると…「ふ~んプラグインも作れるのか」「音声入力プラグインなんてものも作れるのか」「うん?音声入力!」。
サービスということで無意識にhttp通信のようなものを考えていましたが、マイクがネットワーク越しにあるような入力モードさえあれば、とりあえず用は足せるはず。
あった。-input adinnet
これだ。
複数クライアントからの要求を捌いたりはできそうもないけど、当座はこれで凌げるはず。
あとは先ほどのモジュールモードを組み合わせれば、
Sotaで音声受信(お忘れかもしれませんが、そもそもの目的はコレ)
↓
音声認識サーバでテキスト化
↓
Sotaでテキストを元にした動作
うんうん、問題なさそう。
マイクで音声データを拾ってそれをネットワークに流す簡単なアプリを作って、先に作ったJulius起動バッチを少し直して、jcontrolのバッチも合わせて都合3つのバッチが完成。
因みに、Juliusはモジュールモードの場合だと先に結果通知先とのコネクションを作成するようなので、
- Julius起動
- jcontrol起動
- ネットマイク(仮名)起動
の順番で実行。この順番なら、途中でマイクを切って、その後再度マイクをコネクトすることができるはず。
なんでそんなことを考えるかって?
音声取得と音声認識後の応答(つまり発話)を同時に実行すると、Sotaが自分でしゃべったことを、また認識しようとするじゃないですか。
でも自分がしゃべる時はマイクを切っておけば(耳をふさぐ)、自分のコトバを聞かなくてすみます(音声データ受信後、直前の自分の発話データの逆位相のデータをかぶせてアクティブノイズキャンセラーとすればよいのですが、現時点では手が出ません)。
幼年期の終り
音声認識にかかわる仕組みは(とりあえず)できたっぽい。
これで、認識結果のテキストを手ごろな音声合成(例えばOpen JTalk)でそのまま発話すれば、オウム返しに会話をするはず(長くなるのでその件はまた今度)。
人間でいえば生後1~2歳の赤ちゃんにはなったはず。
次は、会話に応じてそれなりの応答を返す、もっと大人なシステムにしてみます(いつになるやら)。
以上、ten@蓼科情報でした。
CeVIOをインストールして音声編集をしてみました
今日CeVIO Creative Studio S 4.1の30日無料体験版をインストールして音声編集してみました。
どんなに難しいかと思っていましたが、かなり簡単でした。
①セリフ欄に会話したい内容を入力
②キャスト欄から3人のうち1人を選択
③再生ボタンを押す
これだけで入力した内容を会話してくれます。
(1)元気いっぱいの女の子をイメージ?
※上の画面の女の子はもう1パターンのイメージがありました
(2)ツンデレ(多分ね…)をイメージ?
(3)イケメン男性をイメージ?(タカハシって…)
声の大きさやスピード、元気の良さとかを調整してケースバイケースの音声を作成できます。
今、ロボットに会話させる音声を必死に作っているけれど…
40過ぎたオッサンのセンスでどこまでのものが作成出来るか不安で一杯です(笑)
興味がある人は簡単に編集出来るので試してみて下さい。
「暮らしとロボット展」にいってきました
8月12日(金)にSotaプログラミング講習会にいきまして、テンションあがっているところへスタッフさんから紹介されたら行くしかないと『暮らしとロボット展』にいってきました!
『暮らしとロボット展』は新宿高島屋で8/14(日)までの開催でしたので、ぎりぎり見に行けてよかったです。
ε-(´∀`*)ホッ
登場するロボットはパンフレットにも大きく載っている我らがSotaくんをはじめ、ロボホンやPepperなど数多くのロボットが展示されていました。
子供たちに混じって大人もロボットに話しかけている姿をみて、 人工知能を備えたコミュニケーションロボットが、色々できることが増えると、 もっと身近なパートナーになっていくんだろうなと感じました。
あと、ニコニコ超会議でも話題になった『ロボット大喜利』 本当にSotaくんがかわいかったです!!
他にも『ドラえもんのひみつ道具』を感じられる最新技術の紹介がありました。
(・`д´・;)ス、スゴスギル・・・。
ドラえもんで育った身としては、とても感慨深いものです。
第二回が開催されたあかつきには、ぜひ遊びに行ってみてください。
ケーブルカーで行こう!
前の記事で「音声認識やってみよう」と勇ましくいったものの、調べれば調べるほどニュービー君には山頂が高すぎることが身に染みてきました。
さながら、全くの初心者がいきなりエベレストに登頂しようとしているようなものでしょう。
でも幸い多くの方々が、いわば「ケーブルカー」とも言える各種ツール類を用意してくれているので、自力登山は今度にして、まずはケーブルカーで山頂の景色を眺めに行きます(もちろん勉強は続けますって。ホントだよ)。
では出発!
来た、見た、勝った
さて、どのケーブルカーに乗るか選ばなければ・・・
もちろん乗り心地がいいものがいいし、乗りやすいものがいい。
値段もあまりかからないほうが嬉しい。
クラウドで音声認識サービスが色々出回っているし、性能面では問題ないのですが、無料では一日50発話しか使えない(もちろん有料にすればいいのですが、今回はお試しだし)とか、面倒なユーザ登録が必要(可能な限り私は自分のデータをネットに出したくない人なので)だったりとか、ちょっと悩んじゃいました。
で、githubでなんかないかなとgithub 音声認識
で検索したところ、Juliusにヒットしたわけです。
おお!日本語大語彙連続音声認識エンジンですと?
コの業界ってどうしても洋物が多いのですが、音声認識って英語と日本語ではだいぶ勝手が違いますよね?
人間だって三歳位までに、耳の機能が英語に特化したり日本語に特化したりとカスタマイズされるそうですし。
【言語別周波数】
人間が聞き分けられる周波数は20Hz~20KHzですが、言語にも周波数範囲があります。
日本語:0.13KHz~1.5KHz
英語:2KHz~12KHz
英語って日本語よりもかなり周波数が高いのです。
日本語と銘打ってるエンジンは重要ですよ、奥さん。
【日本語音声認識】
Juliusが日本語音声認識と謳っているのは、日本語専用の認識方法をとっている訳でなく、
日本語で学習済みということです。
エンジンはそのままに英語で学習させれば、英語音声認識となるはずです(多分)。
いずれは自分で一から学習させたいですけど、また今度ということで。
という訳で、Juliusを使ってみることにしました。ところで、これの読み方って「ユリウス」でいいんですよね?
インストール
先ほどの検索で上位にでてきたサイトにアクセスして、一通り眺めてみると、どうやらJuliusディクテーション実行キットというのがよさそう。
素直にそれをダウンロードして、zipファイルを早速展開。
伝統的にReadMeを読んでみれば、使い方はとっても簡単。
さっそくGMM(混合ガウスモデル)版を試したところ、「おー認識する!」。
でも、ちょっと誤認識が多いかも・・・軽くていいんだけどね(自分では何もしてないのに偉そうに)。
よ~し、続けてDNN(ディープニューラルネットワーク)版もやってみよう。
何々、Python環境が必要なのか。
機械学習といえばPython
Win7を使ってた時は、Pythonも一通り入れてたのですが、この度Win10にアップグレードするにあたり、クリーンインストールを行ったので、ディスクはスッキリきれいになっていたのでした。
色々ライブラリを入れるのも面倒なので、Anacondaで一気に入れちゃいましょう。
バージョンはどうしよう?やっぱり新しいほうがいいよね?よ~し3.5にしちゃうぞ!
Juliusは2.7と言ってるけど、少しぐらいなら3.5に直しちゃうもんね。
わかる人にはわかると思いますが、2.7と3.5の間には深くて大きな溝があるのでした。
初めてのDNN
ここのサイトから、Python3.5のWin-64bit版をダウンロード。
落としてきたexeを実行して、ウィザードにポチポチと答えてインストール。
特に問題もなくインストールが完了したので、run-win-dnn.batを実行。
3つのコマンドが実行され、DOS窓(コマンドプロンプトのことね)が3つ表示されるはずが…
- julius.exeの窓が開き「Stat: vecin_net: waiting connection...」と表示されて待機し、
- 2つ目の窓は一瞬で閉じられ、
- 3つ目の窓はいくらかの出力を行ったあと、retryを繰り返して閉じる。
- 最初の窓は虚しく何かを待ち続けている
となってしまった。
まあ、予想はしていたことですので、冷静にrun-win-dnn.batをエディタで開いて、2つ目のコマンドを確認すると、
start python .\bin\common\dnnclient.py dnnclient.conf
やっぱりPythonですか。
エラーを確認するため、DOS窓を開いて手動実行。
> python .\bin\common\dnnclient.py dnnclient.conf
common\dnnclient.py dnnclient.conf
File ".\bin\common\dnnclient.py", line 46
print "unkown switch"
^
SyntaxError: Missing parentheses in call to 'print'
print文でこけてる…
parenthesesとはカッコのこと。 どうやらprint文の文法が変わったよう。
printなんて楽勝
Python3でprint文は関数に変わって、その結果、
print "abc"
↓
print("abc")
となったみたいです。
dnnclient.pyの中にprint文は2ヶ所しかなかったので、とりあえず関数に変更して再度手動実行。
「Waiting for connections...」と表示されて待機状態となった。よしよし。
バッチ再実行
再度run-win-dnn.batを実行。
無事3つの窓が開き、3つ目の窓に「<<< please speak >>>」と表示される。
そこで「こんにちは」と発話したところ、大量のエラーを表示して窓3が、続いて窓2が消える。
やはりPython2でなければならないのか?
デバッグ
往生際悪く、Python3で動くようにしてみようと決意。
DOS窓を3つ開いてそれぞれでコマンドを手動実行。
案の定Pythonが
TypeError: Can't convert 'bytes' object to str implicitly
とエラーを出している。
buffer += tmpdata
が問題のロジックだが、バイト列を文字列に暗黙変換できませんというエラー。
バイト列は文字コードの配列と思えるのだが、文字列に変換できないのだろうか?
嫌な予測だけど、文字コード関連のエラーか?
調べたら、案の定文字列とバイト列が明確に区別されるようになっていた。
バイト列を文字列(unicode)にするなら、エンコード処理を差し込む必要があるけど、これはちょっと、チョチョイと直すという訳にはいかないので、あきらめてPython2を入れなおしましょう(問題個所が分かれば直すこと自体は簡単だけど、問題個所が検索だけでは特定できず、ロジックを追う必要があるので)。
Python2環境構築
Python3をアンインストールしてPython2を入れることも考えたのですが、Anacondaは別バージョンの仮想環境を作れたはずなので、せっかくだからトライ。
C:\>conda create -n py2 python=2.7
py2の名前で仮想環境ができたか確認。
C:\>conda env list
py2 C:\Users\****\Anaconda3\envs\py2
root * C:\Users\****\Anaconda3
仮想環境py2に切り替える。
C:\>activate py2
(py2) C:\>python --version
Python 2.7.12 :: Continuum Analytics, Inc.
仮想環境から抜ける
(py2) C:\>deactivate
C:\>
Yeah!できたぜ。
念のため、仮想環境の削除のやり方も書いておきましょう(もちらん実行はしてないので、未検証)。
> conda remove -n py2 --all
おぉっと忘れてた。numpyも入れなきゃいけなかったんだ。
C:\>activate py2
(py2) C:\>pip install numpy
Collecting numpy
Using cached numpy-1.11.1-cp27-none-win_amd64.whl
Installing collected packages: numpy
Successfully installed numpy-1.11.1
本当は最初に仮想環境を作るときに、numpyも入れとけばよかったのだけど・・・
C:\>conda create -n py2 python=2.7 numpy
改めてJulius-DNNを実行
起動バッチに仮想環境への切り替えを仕込み、
activate py2 ←これを挿入
start .\bin\windows\julius.exe -C main.jconf -C am-dnn.jconf -demo -charconv utf-8 sjis
timeout 10
start python .\bin\common\dnnclient.py dnnclient.conf
timeout 2
start .\bin\windows\adintool -in mic -out vecnet -server 127.0.0.1 -paramtype FBANK_D_A_Z -veclen 120 -htkconf model\dnn\config.lmfb.40ch.jnas -port 5532 -cvn -cmnload model\dnn\norm.jnas
で、起動バッチを実行。
ムム。何も起きない?
どうやらactivate py2
で環境を変えると、その時点でバッチ実行が停止してしまうみたい。
仕方ないので、DOS窓を開いてpy2に切り替えた後、そこから起動バッチを実行。この辺りは、あとでもっとうまい手を考えよう。
恐る恐る、小声(別に小声だからうまくいくわけではないのですが)で「こんにちは」と発話したら、しばらくして「こんにちは」と表示されました。
Oh yeah!大成功!!
色々試してみたけれど、確かにGMM版より認識率が高いみたい。
但し、それ相応の処理時間がかかるのが否めないのは仕方ないか(ちょっと一拍置くくらいだけど)。
とりあえず、ここまででJuliusの動作確認は完了。
以上、ten@蓼科情報でした。
君の声が聴きたい
うちのSotaくん(Vstoneさんの所から養子として来たロボット)は7月から耳が聞こえなくなってしまいました。
正確には、聞こえるんだけどコトバがわからなくなったのですね。
人間でいえば「感音性難聴」ということになるのでしょうか?
【感音性難聴】
音は聞こえるのだけれど、言葉が聞き取れないといった症状を表す難聴の一種。
軽度の場合だと本人も気づかず、
・会議等の多人数の会話が聞き取れない→自分の意見を言わないヤツ
・人の話を良く聞き返す→うっとうしい。聞く気がないヤツ
・呼ばれても気づかない→人を無視する嫌なヤツ
等々、対人コミュニケーションで印象が悪くなり、人間関係に悪影響があるようです。
私自身は視力が悪いのですが、耳だって当然同じように機能低下することもあるのに気づかされました。
こういうことに思い至らず、人に悪感情を持ったこともあるかも・・・反省!!
Sotaの場合、音声認識はクラウドサービスを利用しているのですが、それが7月から有料になったため、音声認識機能が使えなくなったのですね(甲斐性なしのお父さんでゴメン)。
マイクは無事だし、だったら自分たちでやってみようか…ということで、音声認識はじめま~す。
そもそも音って何?
物理学での音とは、気体や液体(媒質)の振動(波・粗密波)のことです(個体を伝わる音もあります)。
特に人間を対象とする場合、20Hzから20KHzまでの音波を感知できる(聞こえる)ため、この周波数の音波を特に音と呼びます。
20KHzよりも高い音を超音波、20Hzよりも低い音を低周波音と呼びます。
音の聞こえる範囲は個人差や年齢差や性差があり、一般に年齢が高くなるほど高い音が聞こえなくなります。
耳とマイク
音を受信するセンサーはマイク(マイクロフォン)と呼ばれています。
その構造は
- 空気の振動を受ける
- 空気振動を機械振動に変換する
- 機械振動を電気信号に変換する
というのが基本になります。
最終的な電気信号は、振動の強さを表します。 (いわゆる音声波形を取得している)
では、人間の耳はどんな仕組みになっているのでしょう?
実はまだ完全には解明されていないようです(確からしい仮説はありますが)。
今回、色々と調べてみたのですが、かなり精妙で高度な機構になっているようです。 ただ、基本的には周波数別の強度を信号として検出して、大脳に伝えているようです。
振動と周波数
音声波形(以下波形)はある瞬間の振動の強さを時系列に並べたもので、グラフにすると以下のようになります。
対して、正弦波のような単純で規則正しい音は、速さ・波長・振幅といった、その波を表す値があります。
正弦波は同じ波形が何度も繰り返し規則正しくあらわれるので、単位時間(例えば1秒間)に何回一連の波が現れるかを周波数として表すことができます。
上記のグラフでは横軸が秒を表していますので、1秒間に2回波が来ることが分かります。この場合、周波数は2Hzとなります。
AIにも人間と同じ聴覚を与えようとか、人間をモデルにして機械学習を行おうという場合、この波形を周波数で表現する形に変換しなければなりません(でなければ、多分人間とは違う認識機構になって、音のとらえ方そのものが人間には理解できないものになる気がします)。
フーリエ変換
振動の変化を周波数に変換するとはどういうことでしょう?
音声のような複雑な波形は、一見して周期性とは関係なさそうにみえますが、実は短い区間(音素)に切り分けて、その区間内を複数の正弦波に分解することが可能です。
音声ほど複雑ではありませんが、正弦波よりも複雑な以下の波形を見てください。
上記の波形は、実は以下のように複数の正弦波の合成で作られています。
それぞれ、
- 2Hzで振幅2
- 4Hzで振幅0.5
- 8Hzで振幅1
の3つの正弦波で構成されています。さあ、なんとなく周波数で元の波形を表現できそうな気がしてきませんか?
ということで、横軸に周波数、縦軸に振幅を割り当ててグラフにすると、以下のようになります。
このように、複雑な波形を複数の正弦波に分解し、各周波数とその振幅で表現することをフーリエ変換といいます。
実際にはもっと色々複雑なことをしていますが、概念的にはこんなもんでしょう。
これで声が聞き分けられるのか?
残念ながら、これだけではまだ人間の耳の機能のごく一部を模倣したにすぎませんし、この後には、その信号を処理する脳の働きが控えています。
ノイズの除去、低音部と高音部のバランス、重視する周波数、音素の分割、今聞いた音と記憶にある音とのパターンマッチング、欠落情報の補完等々、人間の感覚器官(とその信号を処理する脳)って本当によくできてますね。
これでまだ、機械学習に投入する前のデータ処理(の一部)なんですから、先は長いです。
以上、ten@蓼科情報でした。