web-dev-qa-db-ja.com

iOSでテキスト(文字列)言語を検出する方法

たとえば、次の文字列があるとします。

let textEN = "The quick brown fox jumps over the lazy dog"
let textES = "El zorro marrón rápido salta sobre el perro perezoso"
let textAR = "الثعلب البني السريع يقفز فوق الكلب الكسول"
let textDE = "Der schnelle braune Fuchs springt über den faulen Hund"

それぞれの使用言語を検出したい。

実装された関数のシグネチャが次のとおりだとしましょう:

func detectedLanguage<T: StringProtocol>(_ forString: T) -> String?

検出された言語がない場合、オプション文字列を返します。

したがって、適切な結果は次のようになります。

let englishDetectedLanguage = detectedLanguage(textEN) // => English
let spanishDetectedLanguage = detectedLanguage(textES) // => Spanish
let arabicDetectedLanguage = detectedLanguage(textAR) // => Arabic
let germanDetectedLanguage = detectedLanguage(textDE) // => German

それを達成するための簡単なアプローチはありますか?

12
Ahmad F

更新済み(iOS 12以降)

簡単に:

次のように NLLanguageRecognizer を使用してそれを実現できます。

_import NaturalLanguage

func detectedLangauge(for string: String) -> String? {
    let recognizer = NLLanguageRecognizer()
    recognizer.processString(string)
    guard let languageCode = recognizer.dominantLanguage?.rawValue else { return nil }
    let detectedLangauge = Locale.current.localizedString(forIdentifier: languageCode)
    return detectedLangauge
}
_


以前の回答(iOS 11以降)

簡単に:

次のように NSLinguisticTagger を使用してそれを実現できます。

_func detectedLangauge<T: StringProtocol>(for string: T) -> String? {
    let recognizer = NLLanguageRecognizer()
    recognizer.processString(String(string))
    guard let languageCode = recognizer.dominantLanguage?.rawValue else { return nil }
    let detectedLangauge = Locale.current.localizedString(forIdentifier: languageCode)
    return detectedLangauge
}
_

詳細:

まず最初に、あなたが何を尋ねているかは主に自然言語処理(NLP)の世界に関連していることを認識する必要があります。

NLPはテキスト言語の検出以上のものであるため、残りの回答には特定のNLP情報は含まれていません。

明らかに、そのような機能の実装はそれほど簡単ではありません。特に、文や単語に分割するなど、プロセスの詳細に注意を向け始めた後、名前や句読点などを認識した後で...骨の折れるプロセス!自分でそれを行うのも論理的ではありません。」;さいわい、iOS doesはNLPをサポートしています(実際には、すべてのAppleプラットフォーム、iOSだけでなく、NLP APIも利用できます)。実装するコアコンポーネントは NSLinguisticTagger です:

自然言語テキストを分析して、品詞と語彙クラスにタグを付け、名前を識別し、見出し語化を実行し、言語とスクリプトを決定します。

NSLinguisticTaggerは、さまざまな自然言語処理機能への統一されたインターフェースを提供し、さまざまな言語とスクリプトをサポートします。このクラスを使用して、自然言語テキストを段落、文、または単語にセグメント化し、品詞、語彙クラス、見出し語、スクリプト、言語など、それらのセグメントに関する情報にタグを付けることができます。

クラスのドキュメントで述べたように、探しているメソッド-Determining the Dominant Language and Orthography section-は dominantLanguage(for:) です。

指定された文字列の主要言語を返します。

戻り値

BCP-47 タグは、文字列の主要言語を識別します。特定の言語を判別できない場合は、「und」タグです。

IOS 5以降にNSLinguisticTaggerが存在することに気付くかもしれません。ただし、dominantLanguage(for:)メソッドはonly iOS 11以降でサポートされています。これは、 Core ML Framework の上に開発:

。 。 。

コアMLは、ドメイン固有のフレームワークと機能の基盤です。コアMLは画像分析のビジョンをサポートします。Foundation自然言語処理(たとえば、NSLinguisticTaggerclass)、および学習した決定木を評価するためのGameplayKit。コアML自体は、アクセラレートやBNNSなどの低レベルのプリミティブ、およびメタルパフォーマンスシェーダーの上に構築されます。

enter image description here

「速い茶色のキツネが怠惰な犬を飛び越える」を渡すことによるdominantLanguage(for:)の呼び出しからの戻り値に基づく:

_NSLinguisticTagger.dominantLanguage(for: "The quick brown fox jumps over the lazy dog")
_

「en」のオプションの文字列になります。ただし、これまでのところ望ましい出力ではないため、代わりに「英語」を取得することが期待されています。まあ、それはまさに Locale 構造から localizedString(forLanguageCode:) メソッドを呼び出して、取得した言語コードを渡すことで取得できるものです。

_Locale.current.localizedString(forIdentifier: "en") // English
_

すべてをまとめる:

「Quick Answer」コードスニペットで述べたように、関数は次のようになります。

_func detectedLangauge<T: StringProtocol>(_ forString: T) -> String? {
    guard let languageCode = NSLinguisticTagger.dominantLanguage(for: String(forString)) else {
        return nil
    }

    let detectedLangauge = Locale.current.localizedString(forIdentifier: languageCode)

    return detectedLangauge
}
_

出力:

予想通りです:

_let englishDetectedLangauge = detectedLangauge(textEN) // => English
let spanishDetectedLangauge = detectedLangauge(textES) // => Spanish
let arabicDetectedLangauge = detectedLangauge(textAR) // => Arabic
let germanDetectedLangauge = detectedLangauge(textDE) // => German
_

注:

次のように、指定された文字列の言語名を取得できない場合もあります。

_let textUND = "SdsOE"
let undefinedDetectedLanguage = detectedLangauge(textUND) // => Unknown language
_

または、nilの場合もあります。

_let rabish = "000747322"
let rabishDetectedLanguage = detectedLangauge(rabish) // => nil
_

それでも、有用な出力を提供するための悪い結果ではありません...


さらに:

NSLinguisticTaggerについて:

NSLinguisticTaggerの使用法については詳しく説明しませんが、特定のテキストの言語を単に検出するだけでなく、いくつかの非常に優れた機能が存在することに注意したいと思います。かなり単純なの例:タグを列挙するときにlemmaを使用すると、- 情報の取得時に非常に役立ちます 、「運転」という言葉が「運転」という言葉を渡すことを認識することができるからです。

公式リソース

Appleビデオセッション

また、CoreMLに慣れるために:

20
Ahmad F

NSLinguisticTaggerのtagAtメソッドを使用できます。 iOS 5以降をサポートしています。

func detectLanguage<T: StringProtocol>(for text: T) -> String? {
    let tagger = NSLinguisticTagger.init(tagSchemes: [.language], options: 0)
    tagger.string = String(text)

    guard let languageCode = tagger.tag(at: 0, scheme: .language, tokenRange: nil, sentenceRange: nil) else { return nil }
    return Locale.current.localizedString(forIdentifier: languageCode)
}

detectLanguage(for: "The quick brown fox jumps over the lazy dog")              // English
detectLanguage(for: "El zorro marrón rápido salta sobre el perro perezoso")     // Spanish
detectLanguage(for: "الثعلب البني السريع يقفز فوق الكلب الكسول")                // Arabic
detectLanguage(for: "Der schnelle braune Fuchs springt über den faulen Hund")   // German
4
Max Lebedev

NSLinguisticTaggerのような短い入力テキストでhelloを試しましたが、常にイタリア語として認識されます。幸いにも、Apple最近追加された NLLanguageRecognizer はiOS 12で利用可能で、より正確なようです:D

import NaturalLanguage

if #available(iOS 12.0, *) {
    let languageRecognizer = NLLanguageRecognizer()
    languageRecognizer.processString(text)
    let code = languageRecognizer.dominantLanguage!.rawValue
    let language = Locale.current.localizedString(forIdentifier: code)
}
2
Tai Le