こんにちは、音楽の聴き過ぎでイヤホンがすぐ壊れてしまうことが悩みの佐藤です。
少し前のデータになりますが、楽天インサイトの調査(2021年)によると、
音楽を聴く人のうち約4割の人が「ほぼ毎日聴く」と回答しているそうです。
(https://insight.rakuten.co.jp/report/20210518/)
サブスク全盛の今、私たちは呼吸をするように音楽を、
そしてその音楽に込められた歌詞を体内に取り込んでいることになります。
しかし、ここでふと、ある懸念が頭をよぎりました。
我々が毎日摂取しているその歌詞、医学的に見て「健康」なのでしょうか?
これ、冷静に考えると身体的・精神的にかなり危険な状態ではないでしょうか?
もしこれを冗談とか比喩とかが通じないタイプの人が聞いたら即入院を勧めるレベルかも•••。
ということで今回は、AWSの医療文書解析AIサービス Amazon Comprehend Medical を使い、
アーティストの歌詞を勝手に問診し、医学的な観点から最も不健康な楽曲はどれなのかを
至って真面目に!技術検証しようと思います。
Amazon Comprehend Medical とは?
あえて自然言語処理を用いずやってみる
まずは今回の主役、Amazon Comprehend Medical(以下ACM)について簡単にご紹介します。
通常、AWSでテキスト分析を行う場合は「Amazon Comprehend」を使用します。
こちらは感情分析(ポジティブ/ネガティブ)や、一般的なエンティティ抽出(人名、地名、組織名など)が得意です。
しかし、今回の目的はあくまでアーティストの問診票作りです。
ならば「部位:Chest(胸部)」「症状:Pain(疼痛)」と、具体的かつ医学的に判定してもらう必要があります。
ACMは、機械学習を使用して非構造化テキスト(医師のカルテ、治験データなど)から、病状から薬剤に至るまで、幅広い医療情報を高精度に抽出することに特化したサービスです。
本来は、膨大な医療記録を効率的に処理し、医療従事者の負担を減らすために使われる非常にお堅いサービスなのですが、「医学用語以外をノイズとして無視する」「比喩を理解しない」という活用?して勝手にアーティストを診断してあげようってわけです。
歌詞をどうやって「診断」する?
Amazon Translate で ACM が読める状態に
ですが、今回の検証には大きな壁があります。
ACMは現在、日本語のテキスト解析に対応していないのです(英語のみ)。
J-POPの歌詞は当然日本語ですよね。
「日本語未対応なら、英語に翻訳してから読ませればいいじゃない」
というマリー・アントワネット的な発想で、間に Amazon Translate を噛ませてみることにしました。
実はこの Amazon Translate を挟むという構成も、今回の検証結果に大きく関わってきます。
こいつがどんな翻訳を見せてくれるのか、J-POP特有の抒情的な歌詞をどう英語に落とし込んでくれるのか。
期待が高まります。
構成図と処理フロー
今回はこんな超簡易的パイプラインを組んでみました。
2. 翻訳:Amazon Translate で英語に翻訳
例:「君がいなくて胸が苦しい」 → “My chest hurts without you”
3. 診断:Comprehend Medical (
DetectEntitiesV2 API) に投げる判定:Anatomy: Chest, Condition: Pain
4. アウトプット:抽出された病名・症状リストと、信頼度スコア(Confidence Score)
「恋の痛み」を強制的に診断させる、近年稀に見る謎ETLパイプラインの完成です。
実践!J-POP患者たちのカルテ
Python を使ってスクリプトを書き、実際にいくつかの「名曲」を診断にかけてみました。
ACM 先生は、アーティストの魂の叫びをどう受け止めるのでしょうか。
今回は著作権的に実際の曲を載せられなかったので、本当にありそうな歌詞を AI に生成してもらい投入してみました。
なお今回の実行は CloudShellから Amazon Translate や ACM を呼び出して実行しておりますので、実際にやってみたい方は以下のコードをご利用ください!
▶ ここをクリックして検証用コードを表示する
以下のコマンドを入力してファイルを作成します。
nano doctor_jpop.py
開いたエディタに、以下のコードを丸ごとコピー&ペーストしてください。
import boto3
import time
# ==========================================
# 診断対象のプレイリスト
# ==========================================
PLAYLIST = [
{
"Artist": "失恋太郎",
"Song": "眠れない夜",
"Lyrics": "胸が張り裂けそうで眠れない夜。食事が喉を通らない。"
},
{
"Artist": "炎のロッカー",
"Song": "バーニング・ラブ",
"Lyrics": "燃えるような恋心。叫びすぎて声が枯れた。息ができない。"
},
{
"Artist": "純愛ちゃん",
"Song": "1000年の愛",
"Lyrics": "1000年先も愛を誓う。君の光で目が眩む。体が砕けても守る。"
},
{
"Artist": "健康キッズ",
"Song": "お野菜のうた",
"Lyrics": "お日様を浴びて、トマトとキャベツを食べよう。元気いっぱい。"
},
{
"Artist": "激しいメタル",
"Song": "ブラッディ・レイン",
"Lyrics": "頭が割れるように痛い。血が騒ぐ。毒のようなキス。意識が遠のく。"
}
]
# 設定エリア
TARGET_REGION = 'us-east-1' # Comprehend Medical用
def main():
# クライアント初期化
translate = boto3.client('translate', region_name=TARGET_REGION)
medical = boto3.client('comprehendmedical', region_name=TARGET_REGION)
print(f"--- J-POP 健康診断を開始します(全 {len(PLAYLIST)} 曲) ---\n")
# 結果格納用リスト
ranking_data = []
for track in PLAYLIST:
artist = track['Artist']
song = track['Song']
lyrics = track['Lyrics']
print(f"Now Checking... [{artist} / {song}]")
# 1. 翻訳 (JA -> EN)
try:
trans_resp = translate.translate_text(
Text=lyrics, SourceLanguageCode='ja', TargetLanguageCode='en'
)
en_text = trans_resp['TranslatedText']
except Exception as e:
print(f" 翻訳エラー: {e}")
continue
# 2. 診断 (Comprehend Medical)
try:
med_resp = medical.detect_entities_v2(Text=en_text)
entities = med_resp['Entities']
except Exception as e:
print(f" 診断エラー: {e}")
continue
# 3. 集計
symptom_count = len(entities)
# どんな症状が見つかったかテキストでまとめる
symptoms_list = [e['Text'] for e in entities]
symptoms_str = ", ".join(symptoms_list) if symptoms_list else "なし(健康)"
ranking_data.append({
"Artist": artist,
"Song": song,
"Score": symptom_count,
"Details": symptoms_str
})
# APIレート制限考慮で少し待機
time.sleep(0.5)
# ==========================================
# 結果発表(ランキング表示)
# ==========================================
ranking_data.sort(key=lambda x: x['Score'], reverse=True)
print("\n" + "="*80)
print(f"{'RANK':<5} | {'ARTIST':<15} | {'SCORE (危険度)':<15} | {'DIAGNOSIS (主な症状)'}")
print("="*80)
for i, data in enumerate(ranking_data, 1):
score = data['Score']
if score == 0:
judge = "健康優良児"
elif score < 3:
judge = f"要経過観察 ({score})"
else:
judge = f"即入院 ({score})"
print(f"{i:<5} | {data['Artist']:<15} | {judge:<15} | {data['Details']}")
print("="*80)
if __name__ == "__main__":
main()
以下のコマンドでスクリプトを実行します。
python3 doctor_jpop.py
結果発表!
出力された結果から、特に重症なものをいくつかピックアップして紹介します。
症例1:失恋直後のバラード患者
対象: 失恋太郎 / 『眠れない夜』
まずは定番、失恋ソングです。
「喉を通らない」「心が引き裂かれる」といった比喩表現が、ACM にはどう伝わったのでしょうか。
・SYMPTOM:
Meals don't go through my throat (食事が喉を通らない)・INJURY/TRAUMA:
heart was torn (心臓裂傷)一発目からかなりの大誤診。
「切ない」という情緒は一切考慮されず、嚥下障害や心臓裂傷といった今すぐ外科的な緊急手術が必要なレベルです。
症例2:情熱的なロックバンド患者
対象: 炎のロッカー / 『バーニング・ラブ』
続いて、熱いロックバンド。
「声が枯れるまで」「息ができない」といった表現はどうなるでしょうか。
・SYMPTOM:
voice died (失声症)・SYMPTOM:
can't breathe (呼吸困難)こちらは呼吸器系の疾患ですかね•••?
声が出ず呼吸困難という状態に対して 「要経過観察」 との診断を下しました。
データ可視化:「不健康ランキング」の結果は?
診断結果をスコアリングし、危険度順に並べ替えた出力結果がこちらです。
RANK | ARTIST | SCORE (危険度) | DIAGNOSIS (主な症状)
================================================================================
1 | 激しいメタル | 即入院 (5) | head hurts, Blood..., poison, Consciousness...
2 | 失恋太郎 | 即入院 (4) | heart was torn, Meals don't go...
3 | 純愛ちゃん | 即入院 (3) | love, eyes, body
4 | 炎のロッカー | 要経過観察 (2) | voice died, can't breathe
5 | 健康キッズ | 健康優良児 | なし (健康)
最も医療費がかかりそうなアーティストは?
圧倒的なスコアで1位になったのは「激しいメタル」でした。
「血(Blood)」や「毒(Poison)」といった単語のオンパレードにより、内科・脳神経外科・救急科のすべての項目でハイスコアを叩き出しました。
やはり野菜は正義
一方で、ランキングの最下位(最も健康)に輝いたアーティストがいます。「健康キッズ」です。
『お野菜のうた』に含まれる「キャベツ」「トマト」といった単語に対し、ACMは全く反応しませんでした。
診断結果は 「なし(健康)」。
やはり明らかに健康そうな歌詞に対しては問題なしと診断する ACM、優秀です!
まとめ
今回は Amazon Comprehend Medical を使って、歌詞の「健康診断」をしてみました。
皆さんも、お気に入りの曲を聴いて「いい歌詞だなあ」と感動しているとき、ふと「これ、Comprehend Medical に通したらどうなるんだろう?」と想像してみてください。
きっと、感動が台無しになるはずです笑
今回紹介した Medical 以外にも、画像認識(Rekognition)や時系列予測(Forecast)など、それぞれの目的に特化した AI サービスがたくさんあります。
「こんな使い方したらどうなるんだろう?」という好奇心から、新しい技術の活用法が見つかるかもしれません(今回の使い方は完全に誤用ですが•••)。
ただ今回の処理は、非構造化データ(歌詞テキスト)から構造化データ(病名・部位・確信度)を抽出する、典型的なETL(Extract, Transform, Load)プロセスを応用したもの。
ビジネスの現場でも、「顧客のアンケート(自由記述)」から「不満の原因(商品・配送・接客)」を抽出して数値化したい、というニーズに活かせるのでは?と思いました。
ぜひ皆さんも、お手元のデータで遊んでみてください! それでは、また次回の記事でお会いしましょう。

