[iOS 10] 音声認識から得た文章の形態素解析と品詞分解をしてみた

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

おばんです、iPhoneは5を使っていますが4世代前ということに気づいてさすがに買い替えを検討し始めている田中です。iPhone 6sあたりがほしい。

今回の記事は【iOS 10】SFSpeechRecognizerで音声認識を試してみた | Developers.IOの続きとなります。
出てくるソースコードも、この記事が前提となります。

タイトルはiOS 10と一応銘打ってはいますが、今回使うNSLinguisticTaggerは特にiOS 10からの新機能というわけではなくSFSpeechRecognizerとの合わせ技でiOS 10とつけていますのであしからず。

NSLinguisticTaggerって?

自然言語のテキストを形態素解析してくれたり品詞分解してくれるクラスです。

NSLinguisticTaggerで形態素解析してみる

前回のソースコードに以下の拡張を書きます。

extension ViewController {
    func analyzeText(text: String) {
        // "en" = 英語
        // "ja" = 日本語
        let tagger = NSLinguisticTagger(tagSchemes: NSLinguisticTagger.availableTagSchemes(forLanguage: "ja"), options: 0)
        
        tagger.string = text
        
        // NSLinguisticTagSchemeTokenType
        // Word, Punctuation, Whitespace, Otherで判別が可能。今回はoptionsで.omitWhitespaceを設定して空白を無視するようにしています。
        tagger.enumerateTags(in: NSRange(location: 0, length: text.characters.count), scheme: NSLinguisticTagSchemeTokenType, options: [.omitWhitespace]) { tag, tokenRange, sentenceRange, stop in
            
            let subString = (text as NSString).substring(with: tokenRange)
            print("\(subString) : \(tag)")
        }
    }
}

この時、解析する言語に合わせてspeechRecognizerのLocaleも変更しておきましょう。
(変更しないと、英語を喋っているのに日本語が入力として受け取られたりします)

// "ja-JP"を指定すると日本語になります。
// "en-US"でアメリカ英語
private let speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "ja-JP"))!

追加した拡張を発話の受け取り部分で使用します。

recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest) { [weak self] result, error in
    guard let `self` = self else { return }
    
    var isFinal = false
    
    if let result = result {
        self.label.text = result.bestTranscription.formattedString
        isFinal = result.isFinal
        
        // analyzeTextにbestTranscriptionを渡す
        self.analyzeText(text: result.bestTranscription.formattedString)
    }

    // エラー処理
    .........
    ......
    ...
}

実行結果

日本語

某アニメの僕の嫁のセリフから

「私ね、大学は医学部って決まってるの。だから、私の音楽はもう終わってるってわけ。」

私 : Word
ね : Word
、 : Punctuation
大学 : Word
は : Word
医学 : Word
部 : Word
って : Word
決まっ : Word
て : Word
いる : Word
の : Word
。 : Punctuation
だ : Word
から : Word
、 : Punctuation
私 : Word
の : Word
音楽 : Word
は : Word
もう : Word
終 : Word
わっ : Word
てる : Word
って : Word
わけ : Word
。 : Punctuation

英語

ジョブズのスピーチから、

"The first story is about connecting the dots."

The : Word
first : Word
story : Word
is : Word
about : Word
connecting : Word
the : Word
dots : Word

NSLinguisticTaggerで品詞分解をしてみる

availableで調べると品詞分解は日本語が非対応でできないため英語でやります。

extension ViewController {
    func analyzeText(text: String) {
        // "en" = 英語
        // "ja" = 日本語
        let tagger = NSLinguisticTagger(tagSchemes: NSLinguisticTagger.availableTagSchemes(forLanguage: "en"), options: 0)
        
        tagger.string = text
        
        // NSLinguisticTagSchemeLexicalClass
        // 品詞、イディオムなどで判別が可能。日本語は非対応。今回はoptionsで.omitWhitespaceを設定して空白を無視するようにしています。
        tagger.enumerateTags(in: NSRange(location: 0, length: text.characters.count), scheme: NSLinguisticTagSchemeLexicalClass, options: [.omitWhitespace]) { tag, tokenRange, sentenceRange, stop in
            
            let subString = (text as NSString).substring(with: tokenRange)
            print("\(subString) : \(tag)")
        }
    }
}

実行結果

The : Determiner
first : Adjective
story : Noun
is : Verb
about : Preposition
connecting : Verb
the : Determiner
dots : Noun

ハラショー、完璧に分解してくれています。

まとめ

やはりオフィスで人が聞いてる中で急に英語喋るのとかなかなかハードル高いですねw
大学時代はほんのちょっとだけこのあたりのことをやっていたので懐かしく感じました。

音声認識に関しては日本語、英語とも良いのであとはそのデータをどう扱うかというところで語の分解・解析等のサンプルとして書いてみました。
またここから二次加工としてどうするかでアプリのネタや要素になりそうかとも思います。(例えば端末内辞書と照らし合わせてゴニョゴニョなアプリとか)

参考