Cloud Natural Language API v2を使って日本語文章のコンテンツ分類を試してみた

待っていた 多言語対応 すぐ試し カテゴリ増強 これも嬉しい
2022.11.29

逆Tipsの紹介から始めたいと思います。
この時期必ず飲んでしまう、歳時記では冬の季語に分類されるスターバックスのジンジャーブレッドラテですが、何故か各オンラインフードデリバリーサービスでは注文できません。他の期間限定のドリンクやフードは頼めるのに、です。


▲ ちょっと不便な土地に住む引きこもりが頑張って出かけた時のご褒美に昇格しました

こんにちは。データアナリティクス事業本部 インテグレーション部 機械学習チームのShirotaです。
逆Tipsの紹介から入りましたが、ここからはGoogle CloudのCloud Natural Language APIの役立ちそうな話をしていきましょう。

Cloud Natural Language APIに v2モデルがやってきた!(パブリックプレビュー)

2022年10月18日、Cloud Natural Language APIにて以下のリリースノートが発表されました。

Natural Language Content Classification v2 model is now in Public Preview. This model supports an expanded taxonomy with 1091 content categories and 11 languages. The model is distilled from a Large Language Model with improved performance over the v1 offering.

前回のgcloud CLIコマンドのブログからそのまま引用させてもらいました。前回のブログでは参考程度にしか話せなかったので、今回はCloud Natural Language APIの新しいリリース内容中心に話をしていこうと思います。
上記引用の内容を簡単にまとめると、

  • v1モデルではコンテンツ分類の言語が英語しか対応していなかったが、v2モデルでは英語に加えて11言語(日本語もあります!)対応するようになる

  • コンテンツのカテゴリが1091種類に拡張される(v1モデルでは620種類でした)

というものになっています。
日本語が使えるようになったことがまず嬉しいことではないでしょうか。
パブリックプレビューということで、色々言葉で説明するよりもまずは実際に触っていこうと思います。

Cloud Natural Language API v2モデルをCloud Shellから触ってみた

早速触ってみた話を書こうと思うのですが、Cloud ShellからCloud Natural Language APIを呼び出すに当たってちょっとつまづいたことがあったので簡単にまとめておきます。
本題が早く読みたい!という方や既にAPIを叩ける環境が準備できているという方は「Cloud Shell上でAPIを叩いてみた」という見出しまでスキップして下さい。

初手、クレデンシャル不足でこけた話

Cloud Shellからサクッと呼び出してAPI叩くぞ〜!と思ったのですが事故りました。

{
  "error": {
    "code": 403,
    "message": "Your application has authenticated using end user credentials from the Google Cloud SDK or Google Cloud Shell which are not supported by the language.googleapis.com. We recommend configuring the billing/quota_project setting in gcloud or using a service account through the auth/impersonate_service_account setting. For more information about service accounts and how to use them in your application, see https://cloud.google.com/docs/authentication/. If you are getting this error with curl or similar tools, you may need to specify 'X-Goog-User-Project' HTTP header for quota and billing purposes. For more information regarding 'X-Goog-User-Project' header, please check https://cloud.google.com/apis/docs/system-parameters.",
    "status": "PERMISSION_DENIED",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.ErrorInfo",
        "reason": "SERVICE_DISABLED",
        "domain": "googleapis.com",
        "metadata": {
          "service": "language.googleapis.com",
          "consumer": "projects/XXXXXXXXXXXX"
        }
      }
    ]
  }
}

エラーメッセージをかいつまんで解説すると、「Cloud Shellからlanguage.googleapis.comを呼び出すクレデンシャルがないから呼び出せないよ」と言う権限が足らずに発生したエラーだということが分かりました。
なので、まずはCloud ShellからCloud Natural Language APIを呼び出せるようにサービスアカウントを作成し、権限を付与していきます。
以下作業は全てCloud Shell上で実施しました。

  1. サービスアカウントの作成

今回は natural-language-api というサービスアカウントを作成していきます。
以下コマンドを実行してサービスアカウントを作成しました。

gcloud iam service-accounts create natural-language-api \
--display-name "Use Cloud Natural Language API"
  1. サービスアカウントにログインする認証情報の作成

次に、作成したサービスアカウントにログインするための認証情報を作成し、 key.json に保存します。

gcloud iam service-accounts keys create ~/key.json \
--iam-account natural-language-api@[プロジェクトID].iam.gserviceaccount.com

このコマンドを実行すると、/home/[プロジェクトID]配下にkey.jsonが作成されます。

  1. 作成した認証情報をクレデンシャルの環境変数に設定する

以下コマンドを実行して、作成した認証情報をクレデンシャルの環境変数に設定します。

export GOOGLE_APPLICATION_CREDENTIALS="/home/[プロジェクトID]/key.json"

これで、Cloud ShellからAPIを叩く前準備が完了しました。

Cloud Shell上でAPIを叩いてみた

実際にv2モデルを使ったコンテンツの分類を試してみます。
以下ドキュメントを参考にして、こちらのコマンドを実行しました。

curl -X POST \
     -H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
     -H "Content-Type: application/json; charset=utf-8" \
     --data "{
  'document':{
    'type':'PLAIN_TEXT',
    'content':'サンタさんへ
ルンバとダイソンのドライヤーください
私より'
  },
  'classificationModelOptions': {
    'v2Model': {
      'contentCategoriesVersion': 'V2',
    }
  }
}" "https://language.googleapis.com/v1/documents:classifyText"

返ってきた結果がこちらです。

{
  "categories": [
    {
      "name": "/Beauty & Fitness/Hair Care/Other",
      "confidence": 0.22415838
    },
    {
      "name": "/Hobbies & Leisure/Special Occasions/Holidays & Seasonal Events",
      "confidence": 0.13962884
    }
  ]
}

日本語の文章に対応していますね!「ドライヤー」や「サンタさん」といった単語からこのようなカテゴリに分類してくれたように見えます。
Cloud Natural Language APIは自動で言語を判別してくれるので、例えば上記コマンドのclassificationModelOptionsを以下のように書き換え、v1モデルでコンテンツ分類をさせようとすると以下のようなエラーが出ます。

v1モデルで実行

curl -X POST \
     -H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
     -H "Content-Type: application/json; charset=utf-8" \
     --data "{
  'document':{
    'type':'PLAIN_TEXT',
    'content':'サンタさんへ
ルンバとダイソンのドライヤーください
私より'
  },
  'classificationModelOptions': {
    'v1Model': {
    }
  }
}" "https://language.googleapis.com/v1/documents:classifyText"

日本語非対応エラー

{
  "error": {
    "code": 400,
    "message": "The language ja is not supported for classify_text analysis.",
    "status": "INVALID_ARGUMENT"
  }
}

v2モデルではより少ない単語数の文章のコンテンツ分類も可能に!

実は、v1モデルでは 20字以上のトークン(単語)を含む文章 でないとコンテンツ分類ができない仕様でした。上記に貼っているドキュメントには以下の記述があります。

重要: V1 modelを使用するときに、少なくとも 20 個のトークン(単語)を含むテキスト ブロック(ドキュメント)を classifyText メソッドに指定する必要があります。

v2モデルではこの制約がなくなり、より少ない単語数の文章のコンテンツ分類が可能になっています。
先ほど分類を試した日本語の文章もかなり短かったですが、今回は「Happy Birthday!」というどこからどう見ても短い英文で試してみようと思います。

v1モデルでのエラーメッセージ

{
  "error": {
    "code": 400,
    "message": "Invalid text content: too few tokens (words) to process.",
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.BadRequest",
        "fieldViolations": [
          {
            "field": "document",
            "description": "Invalid text content: too few tokens (words) to process."
          }
        ]
      }
    ]
  }
}

v2モデルでの分類結果

{
  "categories": [
    {
      "name": "/Hobbies & Leisure/Special Occasions/Holidays & Seasonal Events",
      "confidence": 0.69402266
    }
  ]
}

v1モデルでは「単語数が少ないよ」とエラーが出ましたが、v2モデルでは、しっかり「Seasonal Events」のカテゴリに分類されたようです。

Cloud Natural Language APIを使用する際に気にしておくと良いポイント

「サクッと触ってみた」話はここまでなのですが、おまけとしてCloud Natural Language APIを使用する際に知っておくと少し幸せになれる話をします。

モデル以外にもバージョンの指定ができる

最初に少しお話ししたことをおさらいしましょう。
今回のCloud Natural Language APIのv2モデルリリースに伴い、多言語対応の他に コンテンツのカテゴリが 620 → 1091 種類に拡張される というアップデートもあったことを覚えているでしょうか。
このカテゴリですが、バージョン指定することが可能となっています。
APIを叩く時に引き渡す値の中にある contentCategoriesVersion というパラメータで、V1(620種類のカテゴリ)かV2(1091種類のカテゴリ)を選ぶことができます。
またこのパラメータを利用しなかった場合は、 自動でV1が選択されます

ドキュメントに載っていたサンプルコマンドで用いている文章のカテゴリ分類で試してみました。

V1のカテゴリ分類結果

{
  "categories": [
    {
      "name": "/Internet & Telecom/Mobile & Wireless/Mobile Phones",
      "confidence": 0.62584907
    },
    {
      "name": "/Computers & Electronics/Software/Operating Systems",
      "confidence": 0.5433724
    },
    {
      "name": "/News",
      "confidence": 0.38493055
    },
    {
      "name": "/News/Business News/Company News",
      "confidence": 0.10825102
    }
  ]
}

V2のカテゴリ分類結果

{
  "categories": [
    {
      "name": "/Internet & Telecom/Mobile & Wireless/Mobile Phones",
      "confidence": 0.62584907
    },
    {
      "name": "/Computers & Electronics/Software/Operating Systems",
      "confidence": 0.5433724
    },
    {
      "name": "/News/Technology News",
      "confidence": 0.37041685
    },
    {
      "name": "/News/Business News/Company News",
      "confidence": 0.10825102
    }
  ]
}

V2からはNewsカテゴリに Technology News が追加されており、より詳細な分類ができるようになりました。

分類できるカテゴリの一覧は以下ドキュメントを参照して下さい。

v1モデルとv2モデルではカテゴリを返すまでの処理が異なる

v1モデルとv2モデルではカテゴリを返すまでの処理が異なります。
どう異なるかについては、上記ドキュメントから引用したものを記載します。

[V1 model](https://cloud.google.com/natural-language/docs/reference/rest/v1/ClassificationModelOptions?hl=ja) を使用する場合、Natural Language API は、classifyText メソッドによって返されたカテゴリをフィルタリングして、リクエストに最も関連性のあるカテゴリのみを残すようにします。たとえば、/Science と /Science/Astronomy の両方がドキュメントに適用された場合は、より具体的な結果が得られるように /Science/Astronomy カテゴリのみが返されます。

[V2 model](https://cloud.google.com/natural-language/docs/reference/rest/v1/ClassificationModelOptions?hl=ja) では、classifyText メソッドから返されたカテゴリはフィルタリングされません。たとえば、/Science と /Science/Astronomy の両方がドキュメントに適用され、妥当な信頼スコアがある場合には、両方のカテゴリが返されます。

先ほども使ったサンプルコマンドで確認してみました。

v1モデル・V1カテゴリでの分類結果

{
  "categories": [
    {
      "name": "/Computers & Electronics",
      "confidence": 0.61
    },
    {
      "name": "/Internet & Telecom/Mobile & Wireless",
      "confidence": 0.53
    },
    {
      "name": "/News",
      "confidence": 0.53
    }
  ]
}

v2モデル・V1のカテゴリ分類結果

{
  "categories": [
    {
      "name": "/Internet & Telecom/Mobile & Wireless/Mobile Phones",
      "confidence": 0.62584907
    },
    {
      "name": "/Computers & Electronics/Software/Operating Systems",
      "confidence": 0.5433724
    },
    {
      "name": "/News",
      "confidence": 0.38493055
    },
    {
      "name": "/News/Business News/Company News",
      "confidence": 0.10825102
    }
  ]
}

v2モデルでのカテゴリ分類結果では /News/News/Business News/Company News が返されていますが、v1モデルでは /News のみが返ってきています。
ここから、より高いconfidenceが出ている /News カテゴリのみが返ってきていたと推測できるでしょう。
このように、v1モデルとv2モデルではカテゴリの返し方が違うことを知っておくと良いことがあるかもしれません。

今後が楽しみなCloud Natural Language API v2!

2022年11月29日現在ではパブリックプレビュー段階のCloud Natural Language APIですが、すでに使い道の幅が大きく広がりそうで楽しみなものになっていました。
今後も、嬉しいアップデートがありましたら検証してお伝えしていこうと思います!