フォーム読み込み中
システムエンジニアの成瀬です。
日々刻々と進化を続けているAIやクラウドサービスを検証したり、AIを活用したアプリを作ったりしています。
とつぜんですが、赤、オレンジ、青の3つの色について、オレンジは、赤と青のどちらに似ていると思いますか?
多くの人は、オレンジは青よりも赤に似ていると思うのではないでしょうか?
でも、その理由を答えることができますか?
よくある理由としては、オレンジは赤っぽいだとか、赤とオレンジは暖色系だからといったところでしょうか?
それでは、青よりも赤の方が似ていると判断される根拠を、もう少し探ってみたいと思います。
理科の授業などで誰でも一度は目にしている、光のスペクトルを見てみましょう。
光のスペクトルは、人間の眼が認識可能な光の波長の長さの順にならんでいて、この中にも赤、オレンジ、青が含まれています。
それぞれの色のだいたいの位置をマークしてみます。
これを見ても、オレンジは赤に近く、青は遠くにあることから、オレンジは青より赤に似ていると言えそうです。
つまり、色どうしの「似ている」か、「似ていない」かは、光の波長が示す位置が、「近い」か「遠い」かによって説明できると言えるのではないでしょうか?
コンピュータの世界ではおなじみのRGBカラーモデルは、光の三原色(赤緑青)の明るさ(輝度)の組み合わせで表現します。
昔のPCなどはRGBの成分ごとに0か1しか選択できなかったため、1ピクセルが表現できる色は8色しかありませんでした。(つまり、オレンジという色は存在しなかったのです...)
| 色 | R | G | B |
|---|---|---|---|
| 黒 | 0 | 0 | 0 |
| 青 | 0 | 0 | 1 |
| 緑 | 0 | 1 | 0 |
| シアン | 0 | 1 | 1 |
| 赤 | 1 | 0 | 0 |
| マゼンタ | 1 | 0 | 1 |
| 黄色 | 1 | 1 | 0 |
| 白 | 1 | 1 | 1 |
現代のPCでは、RGBごとに0から255の256階調で、約1600万色の表現が一般的となっています。
例えば、オレンジを256階調のRGBで表すと、 R=255, G=127, B=0となります。
私のオレンジは違うという方がいるかもしれませんが、オレンジはどこまでがオレンジかというパラドックスに陥ってしまうので、この場はお許しください。
光の三原色の赤・緑・青とオレンジの各RGBの値を表にまとめると以下のようになります。
| 色 | R | G | B |
|---|---|---|---|
| 赤 | 255 | 0 | 0 |
| 緑 | 0 | 255 | 0 |
| 青 | 0 | 0 | 255 |
| オレンジ | 255 | 127 | 0 |
さて、上の表はR、G、Bの各成分を軸とした3次元データと考えることができます。
それぞれの色を3次元空間上にプロットしてみましょう。
赤、緑、青はそれぞれお互いに対極に位置していて、赤とオレンジは近い位置にいることがわかります。
2点の位置が近いか遠いかを正確に判断するためには、実際に距離を測って比べてみればよいですね。
オレンジと赤の距離は、以下の式で求めることができます。
√ (オレンジのR座標 - 赤のR座標)^2 + (オレンジのG座標 - 赤のG座標)^2 + (オレンジのB座標 - 赤のB座標)^2
スプレッドシートでの計算式は以下の通りで、結果は127となりました。
=SQRT((255 - 255)^2 + (127 - 0)^2 + (0 - 0)^2)
同様にそれぞれの色について、お互いの距離を計算した結果は以下の通りとなりました。
| 赤 | 緑 | 青 | オレンジ | |
|---|---|---|---|---|
| 赤 | 0 | 360.62 | 360.62 | 127 |
| 緑 | 360.62 | 0 | 360.62 | 285.32 |
| 青 | 360.62 | 360.62 | 0 | 382 |
| オレンジ | 127 | 285.32 | 382 | 0 |
オレンジと青の距離が382に対して、オレンジと赤の距離は127となりました。
これで、オレンジは青より赤に似ている(近い)ことが、より明確になったのではないでしょうか?
円周上に等間隔に色を配置した、カラーホイールという図があります。
この図を使って、色どうしの中心からの角度を考えてみましょう。
上のカラーホイールは12色あるので、隣どうしの色の角度は30度になります。
それぞれの色について、お互いの角度を計算した結果は以下の通りです。
| 赤 | 緑 | 青 | オレンジ | |
|---|---|---|---|---|
| 赤 | 0° | 120° | 120° | 30° |
| 緑 | 120° | 0° | 120° | 90° |
| 青 | 120° | 120° | 0° | 150° |
| オレンジ | 30° | 90° | 150° | 0° |
オレンジと赤が30°に対して、オレンジと青は150°でした。
角度を測る意味として、色の階調(スケール)が変わった場合には、距離も変わってしまいますが、角度は一定のままというメリットがあります。
ここでいったん、オレンジのことは忘れて、赤と黄色と緑について考えてみたいと思います。
それぞれの色のRGB成分は以下の表の通りです。
| 色 | R | G | B |
|---|---|---|---|
| 赤 | 255 | 0 | 0 |
| 黄色 | 255 | 255 | 0 |
| 緑 | 0 | 255 | 0 |
いずれの色もB(青)の成分が0なので、RとGの2次元データとして考えることができます。
ここでRとGの各成分の値の範囲を、「0から255の整数」から、「-1.0から1.0の実数」に変換しておきます。(理由は後で説明します)
つまり、最も輝度の高い255が1.0、中間の127が0.0、最も輝度が低い0が-1.0となります。
変換した結果は以下の通りです。
| 色 | R | G |
|---|---|---|
| 赤 | 1.0 | -1.0 |
| 黄色 | 1.0 | 1.0 |
| 緑 | -1.0 | 1.0 |
これらの色をR軸とG軸の平面上にプロットしてみます。
さらに、原点 (0, 0)から、それぞれの色の座標に線を引いてみます。
こうすることで、線と線に挟まれた角度を測ることができるようになります。
(単位系を変換したのは、原点を中心に対極に配置するためでした)
角度は下の図のように、反時計回りに0~180°の範囲になるように測ります。
角度が0°ということは同一なので完全一致、角度が180°ということはは正反対なので完全不一致になります。
代表的な角度と似ている・似ていないの関係を表にまとめておきます。
| 角度 | 似ている・似ていない |
|---|---|
| 0° | 完全一致 |
| 45° | 似ている |
| 90° | どちらでもない |
| 135° | 似ていない |
| 180° | 完全不一致 |
見た目の上では、赤と黄色は90°でどちらでもない、赤と緑は180°なので完全不一致といったところでしょうか。
赤と黄色の線の間の角度を測るためには、以下の式1~4を計算します。
では、実際に計算してみましょう。
赤と黄色のRG成分を再掲しておきます。
| 色 | R | G |
|---|---|---|
| 赤 | 1.0 | -1.0 |
| 黄色 | 1.0 | 1.0 |
式1のスプレッドシートでの計算式は以下の通りで、結果は0.0となります。
=(1.0 * 1.0) + (-1.0 * 1.0)
式2のスプレッドシートでの計算式は以下の通りで、結果は1.41…(√2)となります。
=SQRT(1.0^2 + -1.0^2)
式3のスプレッドシートでの計算式は以下の通りで、結果は1.41…(√2)となります。
=SQRT(1.0^2 + 1.0^2)
式4は分子が0.0なので、結果も0.0です。
=0.0/(1.41... * 1.41...)
さて、結果は90になることを予想していましたが、実際は0.0でした。何か間違っていたのでしょうか?
実は、式4で算出された値は求めたかった角度ではなく、その角度に対するコサイン(cos θ)に等しい値です。
したがって、角度自体を求めるには 計算結果の0.0を逆コサインする必要があります。
スプレッドシート関数だと計算式は以下の通りで、結果は1.57…となります。
=ACOS(0.0)
さらに、逆コサインの単位はラジアン(円周=2πとする単位)であるため、スプレッドシート関数の以下の計算式で角度に変換します。
=DEGREES(1.57...)
計算結果は90になるので、予想していた角度になりました。
さらに、cosθが0.0のときの角度は90°であるということもわかりました。
念のため、角度が90°のときのコサインも計算しておきましょう。
まず、90°をラジアンに変換します。
=RADIANS(90)
結果は1.57…(2/4π)となりました。
次に、ラジアンに変換した値のコサインを計算します。
=COS(1.57...)
結果は0.0となり、角度が90°のときのコサインは0.0になるということが確認できました。
代表的なcos θと角度(ラジアン)との関係を以下にまとめておきます。
| cos θ | 角度 | ラジアン |
|---|---|---|
| 1.00 | 0° | 0 |
| 0.70... | 45° | 1/4π (0.78...) |
| 0.00 | 90° | 2/4π(1.57...) |
| -0.70... | 135° | 3/4π(2.35...) |
| -1.00 | 180° | 4/4π(3.14...) |
さて、ここであらためて「cos θ」に着目してみましょう。
cos θが、1.0の場合は角度が0°なので完全一致、-1.0の場合は角度が180°なので完全不一致といえます。
つまり、角度を計算するまでもなく cos θが示す値を「似ている」か、「似ていない」かの尺度として使えるわけです。
これをコサイン類似度と呼んでいます。
コサイン類似度の意味と角度の関係を表にまとめておきます。
| コサイン類似度 (cos θ) | 意味 | 角度 | ラジアン |
|---|---|---|---|
| 1.00 (√4/2) | 完全一致 | 0° | 0 |
| 0.70... (√2/2) | 似ている | 45° | 1/4π (0.78...) |
| 0.00 (√0/2) | どちらでもない | 90° | 2/4π(1.57...) |
| -0.70... (-√2/2) | 似ていない | 135° | 3/4π(2.35...) |
| -1.00 (-√4/2) | 完全不一致 | 180° | 4/4π(3.14...) |
では本題に戻って、3次元上での赤、オレンジ、青についてコサイン類似度を計算してみましょう。
計算の考え方は上の平面の場合と同じで、計算対象の次元が一つ増えるだけです。
オレンジと赤のコサイン類似度の計算式は以下の通りです。
では、実際に計算してみましょう。
-1.0~1.0の実数に変換した各色のRGB成分は以下の通りです。
| 色 | R | G | B |
|---|---|---|---|
| 赤 | 1.0 | -1.0 | -1.0 |
| 緑 | -1.0 | 1.0 | -1.0 |
| 青 | -1.0 | -1.0 | 1.0 |
| オレンジ | 1.0 | 0.0 | -1.0 |
式1の計算式は以下の通りで、結果は2.0となります。
=( 1.0 * 1.0 ) + ( -1.0 * 0.0 ) + ( -1.0 * -1.0)
式2の計算式は以下の通りで、結果は1.732…(√3)となります。
=SQRT( 1.0^2 + -1.0^2 + -1.0^2 )
式3の計算式は以下の通りで、結果は1.414…( √2)となります。
=SQRT( 1.0^2 + 0.0^2 + -1.0^2 )
式4の計算式は以下の通りで、結果は0.81…( 2/√6)となります。
=2.0 / ( 1.732... * 1.414...)
同様に、各色どうしのコサイン類似度の算出結果を以下の表にまとめておきます。
| 赤 | 緑 | 青 | オレンジ | |
|---|---|---|---|---|
| 赤 | 1.00 | -0.33 | -0.33 | 0.81 |
| 緑 | -0.33 | 1.00 | -0.33 | 0.44 |
| 青 | -0.33 | -0.33 | 1.00 | -0.81 |
| オレンジ | 0.81 | 0.44 | -0.81 | 1.00 |
言葉で表現すれば、オレンジと赤は「かなり似ている」けど、オレンジと青は「かなり似ていない」と言ったところでしょうか。
今回利用する、Vertex AI の Text Embeddings APIは、テキストを渡すと埋め込みによって768次元のベクトルが返ってきます。
ここでのベクトルとは実数の並びを意味していて、埋め込みとはデータをモデルの特徴空間上の点にマッピングすることです。
RGBカラーモデルの例でいえば、オレンジと入力すれば、[1.0, 0.0, -1.0]の3次元データが返ってくることをイメージすると、わかりやすいかと思います。
(ただし、各次元の成分はRGBのようにあらかじめ決まっているわけではありません)
768次元であっても、平面や立体と同様にベクトル間の距離や類似度を計算することができます。
Vertex AI APIを利用するためには、APIを有効にする必要があります。
また、Vertex AI のAPIをプログラムから呼び出すために、サービスアカウントを作成する必要があります。
サービスアカウントで、Vertex AI APIのエンドポイント予測を実行するために必要な権限は以下になります。
「aiplatform.endpoints.predict」
上の権限に該当するロールは以下のいずれかになります。
今回は「Vertex AI Service Agent」をロールとして割り当てることにします。
テキスト埋め込みを取得するカスタム関数の使用方法を以下のように決めておきます。
Vertex AI APIを実行してテキストに対する埋め込みベクトルを取得する関数です。
TEXT_EMBEDDINGS( テキスト)
テキスト:埋め込みベクトルを取得する対象のテキストです。
文字列化された768次元のベクトルです。
(※ 扱いやすくするために、文字列化しておきます)
TEXT_EMBEDDINGS( "トイレに行きたいのですが" )
現在、利用可能なベクトル埋め込みの基盤モデルは「textembedding-gecko」のみで、日本語には未対応のようです。
| モデル名 | textembedding-gecko |
| 最大入力トークン数 | 3072 |
| 出力ベクトル次元数 | 768 |
| 対応言語 | English (en) Spanish (es) Korean (ko) Hindi (hi) Chinese (zh) |
POST https://us-central1-aiplatform.googleapis.com/v1/projects/{プロジェクトID}/locations/us-central1/publishers/google/models/textembedding-gecko:predict
| 名称 | 値 | 説明 |
|---|---|---|
Content-Type (必須) | application/json | リクエストデータの種類(JSON) |
Authorization (必須) | "Bearer {アクセストークン}" | サービス認証に必要 |
※ アクセストークンは別途APIで取得する必要があります。取得方法については、「アクセストークンの取得方法」で説明します。
| フィールド名 | データ型 | 説明 | |
|---|---|---|---|
| instances | オブジェクト配列 | 最大5件まで | |
| content | テキスト | 埋め込みベクトルに変換するためのテキスト 3072トークン以内 | |
| parameters | オブジェクト |
| |
| opt_out | ブーリアン | 学習データへの利用を許可するかどうか
| |
リクエストデータのサンプル
{
instances: [
{
content: "Where is the restroom?"
}
],
parameters: {
opt_out: true
}
}
| フィールド名 | データ型 | 説明 | |||
|---|---|---|---|---|---|
| predictions | オブジェクト配列 | 結果情報 | |||
| embeddings | テキスト | 埋め込み情報 | |||
| values | 実数の配列 | 埋め込みベクトル (実768次数ベクトル) | |||
| statistics | オブジェクト | 統計情報 | |||
| token_count | 整数 | トークン数 | |||
| truncated | ブーリアン | 切り詰められたかどうか
| |||
レスポンスデータのサンプル
predictions: [
{
embeddings: {
values: [ 0.04106621444225311, 0.015827510505914688, ... ],
statistics: {
truncated: false,
token_count: 5
}
}
}
]
上のサンプルの場合、カスタム関数の戻り値として埋め込みベクトルを返すためには、レスポンスデータの predictions[0].embeddings.values を文字列に変換してセットすればよいことになります。
なお、Vertex APIのリクエストは、1分あたり30回の利用制限があります。
利用制限を超過した場合、以下のエラーメッセージが返ってくるので、すこし待ってからリトライしてみてください。
{
code: 429,
message: 'Quota exceeded for aiplatform.googleapis.com/online_prediction_requests_per_base_model with base model: textembedding-gecko. Please submit a quota increase request. https://cloud.google.com/vertex-ai/docs/quotas.',
status: 'RESOURCE_EXHAUSTED'
}
Vertex AI APIの認証に必要なアクセストークンは、Google OAuth APIを使用して取得します。
アクセストークンを取得する処理は、カスタム関数とは別に共通関数として定義します。
POST https://www.googleapis.com/oauth2/v4/token/
| 名称 | 値 | 説明 |
|---|---|---|
Content-Type (必須) | application/json | リクエストデータの種類(JSON) |
| フィールド名 | データ型 | 説明 |
|---|---|---|
| payload | テキスト | grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion={認証トークン} |
※ 認証トークンはJWT(Json Web Token)形式です。詳しい作りかたはここでは割愛しますが、使用するクレームだけ表にまとめておきます。
| 属性 | 値 | |
| HEADER | ||
| alg | RS256 | |
| typ | JWT | |
| PAYLOAD | ||
| iss | サービスアカウントキーのclient_email | |
| scope | https://www.googleapis.com/auth/cloud-platform | |
| aud | https://www.googleapis.com/oauth2/v4/token | |
| iat | 認証トークンの作成時刻(エポック秒) | |
| exp | 認証トークンの有効期限(エポック秒) | |
| フィールド名 | データ型 | 説明 |
|---|---|---|
| access_token | テキスト | アクセストークン |
| expires_in | 整数 | 有効期限(秒) |
| token_type | テキスト | 「Bearer」固定 |
レスポンスデータのサンプル
{
access_token: 'ya29...Uxt8',
expires_in: 3599,
token_type: 'Bearer'
}
ベクトル間の類似度を計算するカスタム関数の使用方法を以下のように決めておきます。
ベクトルどうしの類似度を計算します。
VECTOR_SIMILARITY(ベクトル1, ベクトル2)
ベクトル1:比較する一方のベクトルです。
ベクトル2:比較するもう一方のベクトルです。
※各ベクトルは文字列化されていて、次元数が一致している必要があります。
戻り値
1.0から-1.0の範囲の実数です。
1.0が最も似ていて、-1.0が最も似ていません。
VECTOR_SIMILARITY("[-0.027284255251288414,...]", "[-0.049530670046806335,...]")
上でも出てきたように、ベクトルAとBのコサイン類似度(cos θ)の計算式を以下にまとめておきます。
Google スプレッドシートのカスタム関数は、スプレッドシートとは別の画面のスクリプトエディタから登録します。
// サービスアカウントキー const GCP_CREDS = // この行を選択して、サービスアカウントのキーファイル(JSON)の内容をペーストしてください /** * サービスアカウントでAPIを利用するためのアクセストークンを取得します。 * カスタム関数の内部で使用するための共通関数です。 * * @param {string} client_email 資格情報のclient_email * @param {string} private_key 資格情報のprivate_key * @param {number} expires トークンの有効期間(秒) デフォルト値:1800 * * @return {object} 実行結果 * * copyright (c) 2023 SoftBank Corp. */ function get_access_token_(client_email, private_key, expires = 1800) { const header = { "alg": "RS256", "typ": "JWT" }; const now = new Date(); const iat = Math.floor(now / 1000) const exp = iat + expires const payload = { "iss": client_email, "scope": "https://www.googleapis.com/auth/cloud-platform", "aud": "https://www.googleapis.com/oauth2/v4/token", "iat": iat, "exp": exp, } const header_encoded = Utilities.base64EncodeWebSafe(JSON.stringify(header)) const payload_encoded = Utilities.base64EncodeWebSafe(JSON.stringify(payload)).replace(/=+$/, '') const to_sign = `${header_encoded}.${payload_encoded}` const signature = Utilities.computeRsaSha256Signature(to_sign, private_key); const signature_encoded = Utilities.base64EncodeWebSafe(signature).replace(/=+$/, ''); const jwt = `${to_sign}.${signature_encoded}`; const params = { 'method': 'post', "payload": `grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=${jwt}`, 'muteHttpExceptions': true }; // APIリクエスト let res; try { res = UrlFetchApp.fetch("https://www.googleapis.com/oauth2/v4/token/", params) } catch (e) { console.error(e) throw Error("内部エラーが発生しました") } const res_json = JSON.parse(res.getContentText()) return res_json } /** * テキスト埋め込みAPIを使用して、テキストに対する埋め込みベクトルを取得します。 * 結果は文字列化されたベクトルです。 * * @param {"トイレはどこですか"} TEXT テキスト {文字列} * 埋め込み対象のテキストです。 * @return {string} * * @customfunction * copyright (c) 2023 SoftBank Corp. */ function TEXT_EMBEDDINGS(TEXT) { const url = `https://us-central1-aiplatform.googleapis.com/v1/projects/${GCP_CREDS.project_id}/locations/us-central1/publishers/google/models/textembedding-gecko:predict` let access_info; try { access_info = get_access_token_(GCP_CREDS.client_email, GCP_CREDS.private_key) } catch (e) { console.error(e) throw "内部エラーが発生しました" } const access_token = access_info.access_token const headers = { "Authorization": "Bearer " + access_token } const payload = { "instances": [ { "content": TEXT, } ], "parameters": { "opt_out": true, } } const params = { method: "POST", headers: headers, contentType: "application/json", payload: JSON.stringify(payload), muteHttpExceptions: true, } const res = UrlFetchApp.fetch(url, params) const res_json = JSON.parse(res.getContentText()) if ("error" in res_json) { console.log(res_json.error) throw "内部エラーが発生しました" } const vector = res_json.predictions[0].embeddings.values return JSON.stringify(vector) } /** * ベクトル間の類似度を算出します。各ベクトルは次元数が一致していて、文字列化されている必要があります。 * 結果は1.0(もっとも似ている)から-1.0(もっとも似ていない)の範囲の実数です。 * * @param {"[0.0,0.1]"} VECTOR1 ベクトル {文字列} * 比較する一方のベクトルです。 * @param {"[-1.0,1.1]"} VECTOR2 ベクトル {文字列} * 比較するもう一方のベクトルです。 * @return {string} * * @customfunction * copyright (c) 2023 SoftBank Corp. */ function VECTOR_SIMILARITY(VECTOR1, VECTOR2) { let vec1 try { vec1 = JSON.parse(VECTOR1) } catch (e) { throw "引数:VECTOR1が不正な値です" } let vec2 try { vec2 = JSON.parse(VECTOR2) } catch (e) { throw "引数:VECTOR2が不正な値です" } if (vec1.length != vec2.length) { throw "次元数が一致していません" } // コサイン類似度を計算 const vec12_dot = vec1.reduce((acc, curr, index) => acc + curr * vec2[index], 0); const vec11_dot = vec1.reduce((acc, curr, index) => acc + curr * vec1[index], 0); const vec22_dot = vec2.reduce((acc, curr, index) => acc + curr * vec2[index], 0); const vec1_l2norm = Math.sqrt(vec11_dot) const vec2_l2norm = Math.sqrt(vec22_dot) const cos_theta = vec12_dot / (vec1_l2norm * vec2_l2norm) return cos_theta }
それでは、実際にカスタム関数を使って、以下の4つの料理の類似度を比較してみましょう
なお、この記事の執筆時点では、まだ日本語に対応できていないようなので、いったん英語に翻訳したテキストをカスタム関数(API)に渡します。
炒飯 -> Fried Rice
チャーシュー麺 -> Braised Pork Ramen
オムライス -> Omelette Rice
ナポリタン -> Ketchup-seasoned Pasta
| セル | 入力値 |
|---|---|
| C3 | =TEXT_EMBEDDINGS(B3) |
| C4 | =TEXT_EMBEDDINGS(B4) |
| C5 | =TEXT_EMBEDDINGS(B5) |
| C6 | =TEXT_EMBEDDINGS(B6) |
| セル | D列 | E列 | F列 | G列 |
|---|---|---|---|---|
| 行3 | =VECTOR_SIMILARITY($C3,$C3) | =VECTOR_SIMILARITY($C3,$C4) | =VECTOR_SIMILARITY($C3,$C5) | =VECTOR_SIMILARITY($C3,$C6) |
| 行4 | =VECTOR_SIMILARITY($C4,$C3) | =VECTOR_SIMILARITY($C4,$C4) | =VECTOR_SIMILARITY($C4,$C5) | =VECTOR_SIMILARITY($C4,$C6) |
| 行5 | =VECTOR_SIMILARITY($C5,$C3) | =VECTOR_SIMILARITY($C5,$C4) | =VECTOR_SIMILARITY($C5,$C5) | =VECTOR_SIMILARITY($C5,$C6) |
| 行6 | =VECTOR_SIMILARITY($C6,$C3) | =VECTOR_SIMILARITY($C6,$C4) | =VECTOR_SIMILARITY($C6,$C5) | =VECTOR_SIMILARITY($C6,$C6) |
算出された各料理間の類似度をまとめた結果は以下の通りです。
| 炒飯 | チャーシュー麺 | オムライス | ナポリタン | 最高 | 最低 | |
|---|---|---|---|---|---|---|
| 炒飯 | 1.00 | 0.71 | 0.80 | 0.67 | オムライス | ナポリタン |
| チャーシュー麺 | 0.71 | 1.00 | 0.69 | 0.73 | ナポリタン | オムライス |
| オムライス | 0.80 | 0.69 | 1.00 | 0.67 | 炒飯 | ナポリタン |
| ナポリタン | 0.67 | 0.73 | 0.67 | 1.00 | チャーシュー麵 | 炒飯 オムライス |
どうですか? なかなか興味深い結果になりましたね。
炒飯に一番よく似ているのがオムライスなのは、両方ともご飯ものだからでしょうか。
そして、ナポリタンよりチャーシュー麵の方が炒飯に近いのは、同じ中華料理だからですかね。
ナポリタンとチャーシュー麺、炒飯とオムライスの関係についても同様のことが言えそうです。
いずれの結果もあまり違和感がないように感じますがいかがでしょうか?
この前編では、Vertex AI Text Embeddings API を使って、テキストの類似を判別する方法について説明しました。
この方法だけでも、似たような質問に対する回答を検索することは可能ですが、次の後編では生成AIのAPIを使って、質問に関連する文章から回答を生成するカスタム関数を作ってみようと思います。
どうぞお楽しみに!
「活用のためのアイデア」でも触れた通り、Q&Aの精度を上げるためには色々な試行錯誤が必要です。また、データセットが大規模になるほど、精度を維持することも難しくなります。
そこで、生成AI導入やシステム構築に不安がある方向けに「Vertex AI DIYプラン」をご紹介します。
Vertex AI DIYプランでは、Vertex AI Search による、 社内文書などのエンタープライズ検索の構築をエンジニアがサポートしてくれます。
興味のある方は、一度相談してみてはいかがでしょうか?
詳細については、関連サービスの「Vertex AI DIYプラン」からご確認ください。
Vertex AI Search を使って社内文書を検索する生成AIを構築してみませんか?
ソフトバンクのエンジニアが構築をサポートします。
Google の生成AIの導入を考えている方はもちろん、どのようなものか確認したいという方でもご活用いただけます。
Google スプレッドシート、Gmail、Google カレンダー、Google Chat、Google ドライブ、Google Meet などのさまざまなサービスがあらゆる働き方に対応する業務効率化を実現します。
Google サービスを支える、信頼性に富んだクラウドサービスです。お客さまのニーズにあわせて利用可能なコンピューティングサービスに始まり、データから価値を導き出す情報分析や、最先端の機械学習技術が搭載されています。
条件に該当するページがございません