初学者向け「Amazon Translate」(AI翻訳サービス)をPythonで利用するには:AWSチートシート
AWS活用における便利な小技を簡潔に紹介する連載「AWSチートシート」。今回は、AWSのAI翻訳サービス「Amazon Translate」をPythonで利用する方法を紹介する。
「Amazon Web Services」(AWS)活用における便利な小技を簡潔に紹介する連載「AWSチートシート」。今回は、AWSのAI翻訳サービス「Amazon Translate」をPythonで利用します。以下、Translateに用意されているメソッドを概観し、その使い方を紹介します。
「Amazon Translate」とは
AWSには、事前トレーニング済みのAI(人工知能)を手軽に利用できる「AIサービス」が多数用意されており、その内容はコンピュータビジョンから言語、レコメンデーション、予測と多岐にわたります。
今回紹介するAmazon Translate(以下、Translate)は、深層学習を利用したニューラル機械翻訳によってテキストを翻訳するAIクラウドサービスです。サポート言語は日英、英日など71言語間で4970通りの組み合わせが提供されており、中国語の簡体字と繁体字など、細分化されている言語もあります(2021年8月の本稿執筆時点)。
Translateを利用することで、Webサイトやアプリケーションを容易にローカライズすることができ、また、大量のWord文章などをバッチ処理でも翻訳できます。
AWSの「AIサービス」はコンソール画面から利用できますが、開発を念頭に置かなくても、慣れてくれば今回のようにAPIを利用する方がより便利で効率的に感じてくるでしょう。本稿がそのように利用するきっかけになれば幸いです。
利用料金について
Translateは従量課金制で、APIに送信されたテキストの文字数(空白を含む)に応じて毎月課金されます。料金はリアルタイム翻訳と標準バッチ翻訳共に共通で、リクエスト100万字に対して15.00ドルです。一方、「Active Custom Translation」によるバッチ処理は、リクエスト100万字に対して60.00ドルです。
なおTranslateは、無料利用枠の対象になっており、リアルタイム翻訳と標準バッチ翻訳は最初のリクエストから12カ月間は1カ月当たり200万字まで、無料で利用することができます。Active Custom Translationによるバッチ処理は最初のリクエストから2カ月間は、1カ月当たり50万字まで、無料で利用できます(ただし、無料利用枠を超えた場合には従量課金が適用されます)。
必要条件
本稿では、読者の環境で下記要件が満たされていることを仮定しています。
- AWSアカウントを有しており、「AWS Identity and Access Management」(IAM)ユーザーに必要な権限(今回ならTranslateと「Amazon S3」関連)が付与されていること。ホームディレクトリにAPIを利用する認証情報が保存されていること
- AWSが提供するPython用のSDK「Boto3」がインストールされていること
なおこれは必須ではありませんが、以下のサンプルコードは「Jupyter Notebook」での実行を想定しています。
メソッド一覧
Amazon Translateには以下のメソッドが用意されています。
メソッド名 | 機能 | 引数 | 戻り値 |
---|---|---|---|
translate_text | 入力テキストを翻訳する | 入力テキスト、カスタム用語名、入力言語コード、出力言語コード | 辞書 |
start_text_translation_job | バッチ翻訳ジョブを開始する | バッチ翻訳ジョブ名、入力データの情報、出力データの情報、データアクセスロールARN、入力言語コード、出力言語コード、カスタム用語名、並列データ名、ClientToken | 辞書 |
stop_text_translation_job | 実行中のバッチ翻訳ジョブを停止する | ジョブID | 辞書 |
list_text_translation_jobs | 開始済みバッチ翻訳ジョブの情報を返す | 検索フィルター情報、NextToken、レスポンスの最大値 | 辞書 |
describe_text_translation_job | 特定のバッチ翻訳ジョブの情報を返す | ジョブID | 辞書 |
import_terminology | カスタム用語を作成または更新する | カスタム用語名、マージ方法、説明書き、カスタム用語データ、暗号化キー | 辞書 |
list_terminologies | 作成済みカスタム用語の情報を返す | NextToken、レスポンスの最大値 | 辞書 |
get_terminology | 特定のカスタム用語の情報を返す | カスタム用語名 | 辞書 |
delete_terminology | 特定のカスタム用語を削除する | カスタム用語名 | - |
create_parallel_data | 並列データを作成する | 並列データ名、説明書き、並列データの情報、暗号化キー、ClientToken | 辞書 |
update_parallel_data | 作成済み並列データを更新する | 並列データ名、説明書き、並列データの情報、ClientToken | 辞書 |
list_parallel_data | 作成済み並列データの情報を返す | NextToken、レスポンスの最大値 | 辞書 |
get_parallel_data | 特定の並列データの情報を返す | 並列データ名 | 辞書 |
delete_parallel_data | 特定の並列データを削除する | 並列データ名 | 辞書 |
can_paginate | 各メソッドのページネーションの有無を調べる | メソッド名 | 真偽値 |
generate_presigned_url | 署名済みURLを返す | メソッドとその引数 | 署名済みURL |
get_paginator | メソッドに関するページネータを生成する | メソッド名 | ページネータオブジェクト |
幾つか解説します。
繰り返しますが、Translateの処理は、リアルタイム翻訳と非同期バッチ処理の2種類が提供されています。リアルタイム翻訳は、単一のドキュメントを翻訳する際に利用し、Translateを呼び出すとレスポンスがすぐに返されます。
一方、非同期バッチ処理は、複数のドキュメントを一度に翻訳する場合や、並列データを用いたActive Custom Translationによるカスタム翻訳に利用します。ドキュメント形式はプレーンテキストの他に、HTML、Word、Excel、PowerPoint、XLIFFをサポートしています。
注意点としては、この処理では入出力データをS3で扱うことから、入力用S3フォルダに対する読み取りと出力用S3バケットに対する読み書きを許可するIAMロールを、Translateに対して事前に割り当てる必要があります(なお、入力ファイルをバッケットのトップレベルにおくことはできません)。
また、S3バケットは「Amazon Transcribe」を呼び出す際のAPIエンドポイントと同じリージョンに作成する必要があります。最後に、この非同期バッチ処理は東京リージョンならびに大阪リージョンでは現在提供されていないので、利用する際は適切なリージョンを選択する必要があります。データ容量や文字数の制限も含めて、詳しくは公式ドキュメントをご確認ください。
次に「カスタム用語」とは、企業名やキャラクター名などの独自コンテンツを入力言語と出力言語のペアで記したもの(サポート形式はCSVまたはTMX)で、これを用いるとTranslateのアルゴリズムによらずに該当用語を指定した通りに翻訳することができます。
続いて「並列データ」とは、入力言語の例文と出力言語での訳文をセットにしたもの(サポート形式はCSV、TSV、TMX)で、これを用いると並列データのスタイルや語調、単語の選択を反映するように調節された翻訳ができます。なお、並列データは入力言語または出力言語の一つとして、英語を使用する必要があります。
Translateは入出力ファイルの文字エンコーディングとしてUTF-8を利用します。
ここからは、Translateのメソッドを用いてテキストを翻訳してみます。
translate_textメソッド
translate_textメソッドは、Translateの最も基本的なメソッドです。プレーンテキストをリアルタイムに翻訳します。
今回はサンプルテキストとして、TranslateのWebページでも紹介されている「世界人権宣言(Universal Declaration of Human Rights)」を使用します。本稿では、英文からの和訳のみを行い、和文は日本国外務省Webページに掲載されている仮訳文を参考とします。以下では第二条(Article 2)の第1文を訳しますが、その英文と和文を以下にあらかじめ掲載します。
Article 2 Everyone is entitled to all the rights and freedoms set forth in this Declaration, without distinction of any kind, such as race, colour, sex, language, religion, political or other opinion, national or social origin, property, birth or other status.
第二条 1 すべて人は、人種、皮膚の色、性、言語、宗教、政治上その他の意見、国民的若しくは社会的出身、財産、門地その他の地位又はこれに類するいかなる事由による差別をも受けることなく、この宣言に掲げるすべての権利と自由とを享有することができる。
import boto3 # 使用するリージョン:バージニア北部リージョン region = 'us-east-1' # Translate クライアントを作成 translate = boto3.client('translate', region) # ターゲットの英文 article2_en = ('Everyone is entitled to all the rights and freedoms ' 'set forth in this Declaration, without distinction of ' 'any kind, such as race, colour, sex, language, religion, ' 'political or other opinion, national or social origin, ' 'property, birth or other status.') # 翻訳を実行 response = translate.translate_text( # 翻訳するテキスト Text=article2_en, # 使用するカスタム用語名 # TerminologyNames=['terminology_sample'], # 入力言語コード SourceLanguageCode='en', # 出力言語コード TargetLanguageCode='ja') # 結果を出力 print(response['TranslatedText'])
実行結果は下記のようになりました。
すべての人は、人種、色、性別、言語、宗教、政治的またはその他の意見、国家または社会的起源、財産、出生またはその他の地位など、いかなる種類の区別もなく、本宣言に規定されているすべての権利および自由を受ける権利を有します。
いかがでしょうか。比較的長い文章でも、しっかり訳されていると思います。ただ、ユースケースによっては訳語が適切かどうかチェックしたり、意味上の誤りや文法上の誤りがないかどうかチェックしたりする必要がありそうです。
今回の翻訳であれば、英文中の「colour」は「色」と訳されましたが、外務省の仮訳文では文意に基づいて「皮膚の色」と訳されていました。そこで、ここからは「カスタム用語」を登録して、あらかじめ訳語を指定して翻訳してみます。
import_terminologyメソッド
手順は次の通りです。まず、「カスタム用語」として登録する内容を下記の要領で列挙して、CSVファイルとして保存(ここではファイル名を「terminology_sample.csv」と)します。
en,ja distinction,差別 colour,皮膚の色 national,国民的 social origin,社会的出身 birth,門地
次に、その内容をimport_terminologyメソッドを利用してTranslateに「カスタム用語」として登録します。なお、メソッドの引数「MergeStrategy」は、「新規登録」と「上書き登録」いずれにおいても必須で、値は'OVERWRITE'のみ受け付けます。これにより、既に同名の「カスタム用語名」が登録されている場合、その内容は新しい内容で上書きされることになります。
# 登録するカスタム用語のパス sample_file = 'terminology_sample.csv' # 登録するカスタム用語の読み出し with open(sample_file, 'rb') as file: data = file.read() # カスタム用語名 terminology_name = 'terminology_sample' # カスタム用語を作成 translate.import_terminology( # カスタム用語名 Name=terminology_name, # マージ方法 MergeStrategy='OVERWRITE', # 説明書き Description='Terminology sample for the UDHR', # カスタム用語データ TerminologyData={'File': data, 'Format': 'CSV'})
「カスタム用語」の登録が完了したら、translate_textメソッドが含まれた初めのコードセルを再度実行します。ただし、今回はキーワード引数「TerminologyNames」の箇所を有効にしてください。「カスタム用語」を利用した翻訳の結果は以下のようになりました。
すべての人は、人種、皮膚の色、性別、言語、宗教、政治的またはその他の意見、国民的または社会的出身、財産、門地またはその他の地位など、いかなる種類の差別もなく、本宣言に規定されているすべての権利および自由を受ける権利を有します。
いかがでしょうか。登録された「カスタム用語」の内容が正しく反映された訳文が出力されました。
create_parallel_dataメソッドとstart_text_translation_jobメソッド
続いて、「並列データ」を用いたActive Custom Translationによるカスタムバッチ翻訳です。既述の通り、この方法では「並列データ」内の訳文で用いられているスタイルや語調、単語の選択を反映するように調節された翻訳結果が期待されます。今回は試しに、第一条を「並列データ」として与えてみます。
手順は次の通りです。まず、「並列データ」として登録する内容を下記の要領で列挙して、CSVファイルとして保存(ここではファイル名を「paralell_data_sample.csv」と)します。(なお、テキストに半角のカンマが含まれる場合、そのテキストはダブルクオートで囲む必要があります。また、もしそのテキストにダブルクオートが含まれる場合、その直前にダブルクオートを挿入してエスケープさせる必要があります)。
en,ja <第一条の英文>,<第一条の和文>
そして、そのCSVファイルをS3バケットにアップロードした上で、「create_parallel_data」メソッドを利用してTranslateに「並列データ」として登録します。ステータスが「ACTIVE」になれば利用可能です。
次に、今回行うバッチ処理では、Translateはファイルの入出力にS3を利用することから、ターゲットとなる英文もテキストファイルとしてS3(バケットのトップレベルではなくフォルダ)にアップロードします。
以上の準備が整ったら、start_text_translation_jobを実行してバッチ翻訳を開始します。
なお、Active Custom Translationによるバッチ処理は、現在3つのリージョン(US East《N. Virginia》、US West《Oregon》、Europe《Ireland》)のみで提供されています。
import uuid import time # S3クライアントを作成 s3 = boto3.client('s3', region) # 一意識別子を利用してバケット名を作成 bucket = 'translate-sample-' + str(uuid.uuid1()) # S3にバケットを作成 response = s3.create_bucket(Bucket=bucket) # S3にアップロードする並列データファイルのパス sample_file = 'parallel_data_sample.csv' # S3にアップロードするオブジェクトに指定するキー名 sample_key = sample_file # S3に並列データをアップロード s3.upload_file(sample_file, bucket, sample_key) # 並列データのURI parallel_data_uri = f's3://{bucket}/{sample_key}' # 並列データに付ける名前 parallel_data_name = 'parallel_data_sample' # 並列データを作成 translate.create_parallel_data( # 作成する並列データ名 Name=parallel_data_name, # 説明書き Description='Parallel data sample for the UDHR', # 並列データの情報 ParallelDataConfig={'S3Uri': parallel_data_uri, 'Format': 'CSV'}) # 並列データのステータスを10秒ごとにチェック(筆者実行時の所要時間は2分程度でした) while True: response = translate.get_parallel_data(Name=parallel_data_name) status = response['ParallelDataProperties']['Status'] if status in ['ACTIVE', 'FAILED']: print(' Status:', status) break print('>', end='') time.sleep(10)
# S3にアップロードする入力ファイルのパス target_file = 'Article2.txt' # S3にアップロードするオブジェクトに指定するキー target_key = f'input/{target_file}' # S3に入力ファイルをアップロード s3.upload_file(target_file, bucket, target_key) # バッチ翻訳で使用する入力データのURI target_uri = f's3://{bucket}/input/' # バッチ翻訳で使用する出力データのURI output_uri = f's3://{bucket}/output/' # バッチ翻訳ジョブ名 job_name = 'sample_job_with_parallel_data' # バッチ翻訳ジョブを開始 response = translate.start_text_translation_job( # バッチ翻訳ジョブ名 JobName=job_name, # 入力データの情報 InputDataConfig={'S3Uri': target_uri, 'ContentType': 'text/plain'}, # 出力データの情報 OutputDataConfig={'S3Uri': output_uri}, # S3バケットにアクセスするためのIAMロール DataAccessRoleArn='<data_access_role_arn>', # 入力言語コード SourceLanguageCode='en', # 出力言語コード TargetLanguageCodes=['ja'], # カスタム用語名 TerminologyNames=[terminology_name], # 並列データ名 ParallelDataNames=[parallel_data_name], ) # バッチ翻訳ジョブIDを取得 job_id = response['JobId'] # バッチ翻訳ジョブのステータスを60秒ごとにチェック(筆者実行時の所要時間は35分程度でした) while True: response = translate.describe_text_translation_job(JobId=job_id) status = response['TextTranslationJobProperties']['JobStatus'] if status in ['COMPLETED', 'COMPLETED_WITH_ERROR', 'FAILED']: print(' Status:', status) break print('>', end='') time.sleep(60)
# 出力オブジェクトのprefixを取得 uri = response['TextTranslationJobProperties']['OutputDataConfig']['S3Uri'] prefix = ''.join(uri.partition('output')[1:]) # 出力オブジェクトのkey output_key = f'{prefix}ja.{target_file}' # S3から結果ファイルをダウンロード output_file = f'ja.{target_file}' s3.download_file(bucket, output_key, output_file) # 結果の表示 with open(output_file) as file: print(file.read())
「並列データ」を利用したバッチ翻訳の結果は下記のようになりました。
すべての人は、人種、皮膚の色、性別、言語、宗教、政治その他の意見、国民的または社会的出身、財産、門地またはその他の地位など、いかなる種類の差別もなく、本宣言に定めるすべての権利と自由を受ける権利を有する。
いかがでしょうか。「並列データ」(第一条の英文)とターゲット(第二条の英文)にはフレーズとしてのオーバーラップはなかったことから、訳文に大きな変化はありませんでした。ただ、小さな変更は幾つか生じており、特に、文末はこれまでの「です・ます調」の「敬体」から、仮訳文で用いられている「だ・である調」の「常体」に変化しました。細かく見ると、これまで「および」と訳されていた「and」は、「並列データ」での訳を反映してか、シンプルに「と」と訳されました。
その他のメソッド
最後に、Translate(とS3)のその他のメソッドをまとめて使用して、後片付けをします。手順は次の通りです。まず、「delete_terminology」メソッドを利用して、「カスタム用語」を削除します。次に、「delete_parallel_data」メソッドを利用して、「並列データ」を削除します。最後に、S3バケット内のオブジェクトを全て削除して、S3バケット自体も削除します。
# カスタム用語を削除 translate.delete_terminology(Name=terminology_name) # 並列データを削除 translate.delete_parallel_data(Name=parallel_data_name) # S3バケット内のオブジェクトを削除 response = s3.list_objects_v2(Bucket=bucket) for content in response['Contents']: s3.delete_object(Bucket=bucket, Key=content['Key']) # S3バケットを削除 s3.delete_bucket(Bucket=bucket)
最後に
AI翻訳はこのような簡単なサンプルでも十分楽しめますが、AWSのその他のAIサービスと組み合わせることで、ユースケースの幅は一気に広がります。興味を持った方は公式ドキュメントを参考にしながら、いろいろと試してみてください。
筆者紹介
金 晟基(キム ソンギ)
東京ITスクールでJava研修の講師、IT専門学校の教材、カリキュラム開発、一般社団法人とのプログラミング教育を通じた国際貢献事業などを担当。AWS認定資格は「機械学習 - 専門知識」など
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- クラウド「AI」API入門:AWS/Cognitive Services/Google Cloud/IBM Watsonの比較
「AWS AIサービス」「Azure Cognitive Services」「Google Cloud AIビルディングブロック」「IBM Watson API」という主要AIサービスの一覧表を示し、各サービスを1行程度で説明する。自分でAI/機械学習モデルを作る前に、既存のAIサービスがないか(カスタマイズできないか)を、これで確認しよう。 - 「スマートスピーカー」の中にある「人工知能」は何をしているのか、作り方から理解する
世界の名だたるプラットフォーマーが開発に力を入れる「スマートスピーカー」。どのような手順でどんな処理が行われているのかは完全にブラックボックスだ。「スマートスピーカーを理解するには、自作するのが早道」と提唱する開発者に話を聞いた。 - 「Amazon Connect」の、コールセンターを変える「破壊力」
Amazon Web Services(AWS)の「Amazon Connect」は、コールセンターをクラウド上にソフトウェアで構築できるサービスだ。最大の特徴はコールセンターの構築・運用コストの大幅な削減。だが、従来型のコールセンターシステムを、ビジネスの変化に柔軟に対応できるツールに変えたいという用途にも適している。AWSとセールスフォースの説明に基づき、このサービスをあらためて紹介する。