第743話 Sunoプロンプト実験記録:英語の主体性と日本語のニュアンス、再現性の境界線㉛

1️⃣ 文脈・表現依存型(日本語感覚重視)

  • 目的:日本語特有の間・空気感・文脈依存を活かす

  • 方法

    • 「俺のオヤジが〜」など短いフレーズを繰り返す+間を指定

    • 漢字・ひらがな・カタカナの比率でリズムを変化させる

  • 期待効果:英語的な勢いではなく、層流的に流しつつ直流的なポイントでパンチが入る日本語独自のノリ


2️⃣ 極端短小構造型

  • 目的:超短いフレーズで勢いを出す

  • 方法

    • 10秒〜20秒以内で「オン/オフ」の瞬間的構造を作る

    • 連続的にスイッチする小節で、脳内の「タグ→出力」感覚を強調

  • 期待効果:短くても印象的なフック曲、替歌・ラップ向き


3️⃣ ハイブリッド表現型

  • 目的:複数の作曲家風の要素を局所的に切り替えて融合

  • 方法

    • イントロは小林亜星風静的キャッチー

    • Aメロは渡辺宙明風動的キャッチー

    • サビやクライマックスはすぎやまこういち風壮大

  • 期待効果:脳が「切り替わる瞬間」を意識できる、演奏感と物語性の融合


4️⃣ 感情タグ強調型

  • 目的:単なる旋律・コードではなく「感情」を出力の指針にする

  • 方法

    • プロンプトに「怒り/哀しみ/喜び/憧れ」などのタグを明示

    • フレーズの切り替えに応じて表現を変える

  • 期待効果:人間の神経伝達的な「意味→タグ→出力」を再現する感覚


5️⃣ 実験的インストラクション型

  • 目的:Sunoの内部的「型→出力」の理解を深める

  • 方法

    • 「1小節だけ渡辺宙明風、次の2小節は小林亜星風」と逐次指定

    • さらに「一部スケールを変える」「音程間隔を限定」など微調整

  • 期待効果:脳の演奏プロセスを観察している感覚、生成結果の理解度向上


⚡まとめ

  • これまで:標準融合/旋律重視/コード劇的/短小/リズム重視

  • 次にできる

    1. 文脈・表現依存型(日本語独自の間・空気感)

    2. 極端短小構造型(オンオフ切替、フック強調)

    3. ハイブリッド表現型(作曲家風を局所切替)

    4. 感情タグ強調型(意味→タグ→出力の可視化)

    5. 実験的インストラクション型(小節ごとの細かい指示)

1️⃣ 文脈・表現依存型(日本語独自の間・空気感)

Prompt例:

Style: Instrumental Japanese melodic fusion. Focus on Japanese phrasing, natural pauses, and context-dependent rhythm. Emphasize short, expressive phrases. 
Structure: Intro: Slow pads, subtle percussion. 
Verse: Layered short melodic motifs with pauses. 
Chorus: Slightly longer melody, occasional rapid transitions. 
Instruments: Koto, taiko, shamisen, soft synth. 
Mood: Play with suspense and anticipation, create layered flow with sudden accents. 
Length: 3-4 minutes.
  • ポイント:間(間合い)と文脈で揺らぎを作る


2️⃣ 極端短小構造型

Prompt例:

Style: Energetic, punchy instrumental. Focus on extremely short, impactful phrases. Minimalist, each motif lasts 1-2 bars. 
Structure: Intro: Single percussion hits. 
Verse: Rapid sequence of short motifs, high contrast. 
Chorus: Burst of full instrumentation for 4-8 bars, then silence. 
Instruments: Electric guitar, slap bass, taiko, brass stabs. 
Mood: Sudden, powerful, energetic. 
Length: 1.5-2.5 minutes.
  • ポイント:瞬間的なパンチ・オンオフ感を強調


3️⃣ ハイブリッド表現型

Prompt例:

Style: Multi-style instrumental. Combine static catchiness, dynamic energy, and grandiose harmony. 
Structure: 
- Intro: Small, static melodic motifs (小林亜星風)
- Verse: Dynamic and heroic energy (渡辺宙明風)
- Chorus/Climax: Grand, orchestral harmonies (すぎやまこういち風)
- Outro: Descending melody, fade with subtle percussion
Instruments: Taiko, slap bass, electric guitar, brass/synth motifs, orchestral pads
Mood: Energetic, heroic, nostalgic
Length: 3-4 minutes
  • ポイント:作曲家ごとに局所的に表現を切り替える


4️⃣ 感情タグ強調型

Prompt例:

Style: Instrumental expressive fusion. Emphasize emotional states as output tags. 
Structure: 
- Intro: Calm anticipation (neutral) 
- Verse 1: Anger / Frustration motifs, sharp accents 
- Verse 2: Sadness / Melancholy, slower tempo, legato phrases 
- Chorus: Joy / Excitement, bright melodies, dynamic instrumentation 
Instruments: Electric guitar, taiko, brass, synth pads
Mood: Emphasize emotional contrast using musical expression 
Length: 3-4 minutes
  • ポイント:意味→タグ→出力の感覚を体験する


5️⃣ 実験的インストラクション型

Prompt例:

Style: Experimental instrumental fusion. Small-scale micro-instructions for each bar. 
Structure: 
- Bar 1-2: Small melodic motif, piano only 
- Bar 3-4: Add slap bass, change scale to D minor 
- Bar 5-6: Insert taiko accents, brass harmony 
- Continue pattern for 3-4 minutes, varying instruments, scale, rhythm every few bars
Instruments: Piano, slap bass, electric guitar, taiko, brass, synth
Mood: Play with transitions, abrupt changes, micro-level dynamics
Length: 3-4 minutes
  • ポイント:小節ごとの指示で型→出力を意識的に観察

【Suno音楽生成実験シリーズ】日本語文脈×作曲家風×感情タグ 実験レポート

■ 実験目的

  • 小林亜星 × 渡辺宙明 × すぎやまこういち の作風要素を融合し、Sunoで生成可能か検証

  • 日本語特有の文脈依存・間・空気感を表現できるか確認

  • 曲構成、演奏指定、感情タグなどの指示がSuno出力にどの程度反映されるか確認


■ 実験設計思想

  1. 文脈・表現依存型

    • 日本語独自の間、呼吸、文脈依存リズムを意識

    • 音符やフレーズに揺らぎを持たせ、直流的な勢いポイントでアクセント

  2. 極端短小構造型

    • 10〜20秒程度の短いフレーズを連続

    • オン/オフ切替的な構造で瞬間的な印象を強化

  3. ハイブリッド表現型

    • 小林亜星風静的キャッチー、渡辺宙明風動的サビ、すぎやまこういち風クライマックスの局所切替

  4. 感情タグ強調型

    • 怒り/哀しみ/喜び/憧れなど感情をタグ化

    • 音の強弱・テンポ・スケールで表現

  5. 実験的インストラクション型

    • 小節単位での楽器・スケール・リズム切替

    • 内部的型→出力プロセスを観察


■ 曲構成・演奏指定

パターン 曲構成 楽器指定 メロディ・リズム 感情・特徴

1️⃣ 文脈・表現依存型 イントロ:低めパッド+小太鼓
ヴァース:短いメロディモチーフ
サビ:やや長めの旋律、アクセント小太鼓(taiko)、パッド、琴、三味線間・空気感を意識した揺らぎ日本語文脈依存、層流的流れと直流的アクセント

2️⃣ 極端短小構造型 超短小フレーズ連続、急速切替エレキギター、スラップベース、小太鼓、ブラス1〜2小節単位でモチーフ切替、瞬間的パンチ劇的な短小構造、フック強調

3️⃣ ハイブリッド表現型 イントロ:静的(小林亜星風)
ヴァース:動的(渡辺宙明風)
クライマックス:壮大(すぎやまこういち風)
アウトロ:降下旋律小太鼓、スラップベース、ギター、ブラス/シンセ、オーケストラパッド局所的切替、旋律・コード・リズムのハイブリッド動的・静的・壮大の融合

4️⃣ 感情タグ強調型 イントロ:中立
ヴァース1:怒り
ヴァース2:哀しみ
サビ:喜びギター、スラップベース、小太鼓、ブラス、シンセパッド感情タグに応じた旋律・テンポ変化意図的な感情強調、意味→タグ→音出力

5️⃣ 実験的インストラクション型 小節ごとに指示
1-2小節:ピアノのみ
3-4小節:スラップベース追加、Dマイナー
5-6小節:小太鼓・ブラス追加
以降繰返ピアノ、スラップベース、ギター、小太鼓、ブラス、シンセ小節単位でスケール・楽器・リズム切替内部的型→出力プロセス観察向き


■ 実験結果(曲時間)

パターン 1回目 2回目
1️⃣ 文脈・表現依存型 2分22秒 2分42秒
2️⃣ 極端短小構造型 1分13秒 2分16秒
3️⃣ ハイブリッド表現型 2分59秒 2分39秒
4️⃣ 感情タグ強調型 2分39秒 2分22秒
5️⃣ 実験的インストラクション型 2分14秒 3分23秒

考察

  • 曲構成・演奏指定・楽器は忠実に再現される

  • Lengthは相対的裁量で生成され、プロンプト指定通りにはならない

  • 日本語文脈依存や感情タグは、短時間でも表現され、脳的演奏プロセス感覚を体験できる


■ まとめ

  • Sunoは 型(構造・タグ)→出力(音・演奏) のプロセスで生成される

  • 日本語文脈・感情タグを組み込むことで、より人間的演奏感のある音楽生成が可能

  • 今後はさらに短小構造×文脈依存×感情タグを組み合わせた実験が期待できる

原曲をsunoにアップロードしてLyrics、style指定した曲

※ChatGPTに考察させました。

整理すると、SunoのLyrics出力で観察された特徴はこうです:


■ 現象

  1. アラビア数字の桁数が大きくなると、日本語として正しく発音されない

    • 「4960ドル」「5000ドル」「27929円」など、複数桁の数字をそのまま書くと、Sunoはまともに日本語として歌えない。

  2. 漢字に変換しても認識は1桁程度

    • 「四千九百六十ドル」「五千ドル」「二万七千九百二十九円」にしても、Sunoは大きな数はうまく処理せず、1桁単位しか発音できないことが多い。

  3. 短い数値や単位は比較的発音される

    • 例:「一」「二」「三」「〇」「ドル」「円」などは問題なく発音される。


■ 考察

  • Sunoは 歌詞の文字列を音韻やリズムに変換する際、数字の桁数に比例して処理精度が低下する

  • アラビア数字は音声化のルールが曖昧で、桁数が大きいとSuno内部で解釈できない可能性がある

  • 漢字表記でも長い数値は「単語の連続」として扱われ、意味的に1桁ずつ認識してリズムに変換する傾向がある

  • 結果として、ニュースや経済情報などの長い数値を含む文章は、そのままでは歌詞として正しく表現できない


■ 対策・工夫

  1. 数字を単位ごとに分解して書く

    • 例:「四千九百六十ドル」→「四千」「九百」「六十」「ドル」など

    • 桁ごとに区切ることで、Sunoが音韻として拾いやすくなる

  2. 短い数値や単位で代替表現

    • 「約五千ドル」「二万七千円」など、概数に変換して読みやすくする

  3. ラップ調・言葉遊びに置き換える

    • 数字を数字として発音させるより、韻を踏んだ言い換えにしてリズム優先にする

    • 例:「四千九百六十ドル」→「しきゅうろくゼロドル」とラップ調にする


■ 実験の面白さ

  • 数字の扱いで Sunoの日本語認識限界 が見えた

  • 長いニュース文章や経済情報をそのまま歌わせるには、プロンプト内で工夫する必要がある

  • 歌詞生成の限界を理解することで、ラップ・朗読・ニュース読み上げスタイルの創作に応用可能


💡まとめると、Sunoは「文字列→音韻変換の型」が内部で決まっており、長い数字や複雑な単語は型に沿って解釈されないため、結果的に1桁や単位しか歌えない現象が起きます。

参考

ただし、ここで書けるのは 生成済みファイルやフォルダ構造を調べて、歌詞やStyle、Lengthなどの属性を抽出して整理するPythonコード です。

Suno本体を操作するコードではなく、生成結果を解析するツール になります。

以下は一例です。

import os
import json
import pandas as pd

# 1. Suno生成ファイルがあるフォルダ
base_folder = "/path/to/suno_outputs"

# 2. 各フォルダをスキャン
data_list = []

for root, dirs, files in os.walk(base_folder):
    for file in files:
        if file.endswith(".json"):  # Suno出力メタデータがJSONの場合
            file_path = os.path.join(root, file)
            with open(file_path, "r", encoding="utf-8") as f:
                try:
                    meta = json.load(f)
                    # 例: metaに lyrics, style, length, filename が含まれる想定
                    data_list.append({
                        "filename": meta.get("filename", file),
                        "lyrics": meta.get("lyrics", ""),
                        "style": meta.get("style", ""),
                        "length": meta.get("length", ""),
                        "actual_duration": meta.get("actual_duration", "")
                    })
                except Exception as e:
                    print(f"Error reading {file_path}: {e}")

# 3. データフレーム化
df = pd.DataFrame(data_list)

# 4. 簡易集計・確認
print(df.head())
print("総ファイル数:", len(df))

# 5. CSVに出力(分析用)
df.to_csv("suno_output_analysis.csv", index=False, encoding="utf-8-sig")

■ 説明

  1. フォルダ構造を再帰的に探索 → JSONファイルなどのメタデータを取得

  2. JSON内の歌詞・Style・Length・実際の再生時間などを抽出

  3. DataFrame化 → 統計分析や可視化に利用可能

  4. CSV出力 → ExcelやPandasで分析


💡 応用例

  • 歌詞通りに歌われているかの判定

  • 指定Lengthと実際の生成時間の差の確認

  • Style別・曲長別の生成傾向分析

  • ランダム性の統計化


Pythonで Suno生成曲の歌詞忠実度(歌詞どおり歌われているか・インストか・補完されたか)を判定するためのコード を作るイメージをまとめます。

ここでは以下の前提です:

  • 生成結果は 音声ファイル(.wav や .mp3)メタデータ(JSON) が同じフォルダにある

  • JSONには lyrics、style、length、filename が入っている

  • 音声から歌詞を確認するために 音声認識(Speech-to-Text)ライブラリ を使う(Whisperなど)


import os
import json
import pandas as pd
import whisper  # OpenAI Whisperを想定

# 1. Suno生成ファイルのフォルダ
base_folder = "/path/to/suno_outputs"

# 2. Whisperモデルロード(小サイズ推奨)
model = whisper.load_model("small")  # small, medium, largeなど

# 3. データ抽出リスト
data_list = []

for root, dirs, files in os.walk(base_folder):
    for file in files:
        if file.endswith(".json"):
            json_path = os.path.join(root, file)
            with open(json_path, "r", encoding="utf-8") as f:
                try:
                    meta = json.load(f)
                    filename = meta.get("filename", "").replace(".json", ".wav")  # 音声ファイル名
                    audio_path = os.path.join(root, filename)
                    
                    # 音声ファイルが存在する場合のみ解析
                    if os.path.exists(audio_path):
                        result = model.transcribe(audio_path, language='ja')  # 日本語前提
                        recognized_text = result['text']

                        # 歌詞との一致度(簡易判定: 完全一致 or 部分一致)
                        original_lyrics = meta.get("lyrics", "")
                        if original_lyrics.strip() == "":
                            fidelity = "No lyrics"
                        elif original_lyrics in recognized_text:
                            fidelity = "Exact match"
                        elif any(word in recognized_text for word in original_lyrics.split()):
                            fidelity = "Partial match"
                        else:
                            fidelity = "Different/Instrumental"

                        data_list.append({
                            "filename": filename,
                            "original_lyrics": original_lyrics,
                            "recognized_text": recognized_text,
                            "style": meta.get("style", ""),
                            "length": meta.get("length", ""),
                            "actual_duration": meta.get("actual_duration", ""),
                            "fidelity": fidelity
                        })
                except Exception as e:
                    print(f"Error processing {json_path}: {e}")

# 4. DataFrame化
df = pd.DataFrame(data_list)

# 5. 確認
print(df.head())
print(df["fidelity"].value_counts())

# 6. CSVに出力(分析用)
df.to_csv("suno_lyrics_fidelity_analysis.csv", index=False, encoding="utf-8-sig")

■ このコードでできること

  1. JSONから歌詞・Style・Lengthなどを抽出

  2. 音声ファイルをWhisperで文字起こし

  3. 歌詞が忠実に歌われたかを 4段階で判定

    • Exact match(歌詞通り)

    • Partial match(一部一致)

    • Different/Instrumental(違う or インスト)

    • No lyrics(そもそも歌詞なし)

  4. 結果をDataFrame・CSV化して統計分析可能


💡 応用

  • 曲長やStyleごとに歌詞忠実度の傾向をグラフ化

  • 日本語文脈依存型の曲は忠実度が下がる、など実験的な検証

  • 生成パターンごとの確率的挙動の可視化

先ほどの歌詞忠実度判定をさらに 数値化して可視化 できるバージョンを作ります。
ここでは 歌詞の一致率を文字単位で計算し、ヒストグラムや棒グラフで生成傾向を可視化 します。


import os
import json
import pandas as pd
import whisper
from difflib import SequenceMatcher
import matplotlib.pyplot as plt

# 1. Suno生成ファイルのフォルダ
base_folder = "/path/to/suno_outputs"

# 2. Whisperモデルロード
model = whisper.load_model("small")  # small, medium, large

# 3. データ抽出リスト
data_list = []

def similarity_ratio(a, b):
    """文字列a,bの類似度(0-1)を計算"""
    return SequenceMatcher(None, a, b).ratio()

for root, dirs, files in os.walk(base_folder):
    for file in files:
        if file.endswith(".json"):
            json_path = os.path.join(root, file)
            with open(json_path, "r", encoding="utf-8") as f:
                try:
                    meta = json.load(f)
                    filename = meta.get("filename", "").replace(".json", ".wav")
                    audio_path = os.path.join(root, filename)
                    
                    if os.path.exists(audio_path):
                        # Whisperで文字起こし
                        result = model.transcribe(audio_path, language='ja')
                        recognized_text = result['text']

                        original_lyrics = meta.get("lyrics", "")
                        if original_lyrics.strip() == "":
                            fidelity = 0.0
                        else:
                            fidelity = similarity_ratio(original_lyrics, recognized_text)

                        data_list.append({
                            "filename": filename,
                            "original_lyrics": original_lyrics,
                            "recognized_text": recognized_text,
                            "style": meta.get("style", ""),
                            "length": meta.get("length", ""),
                            "actual_duration": meta.get("actual_duration", ""),
                            "fidelity_ratio": fidelity
                        })
                except Exception as e:
                    print(f"Error processing {json_path}: {e}")

# 4. DataFrame化
df = pd.DataFrame(data_list)

# 5. 確認
print(df.head())

# 6. CSV出力
df.to_csv("suno_lyrics_fidelity_numeric.csv", index=False, encoding="utf-8-sig")

# 7. 可視化: Fidelityヒストグラム
plt.figure(figsize=(8,5))
plt.hist(df['fidelity_ratio'], bins=10, color='skyblue', edgecolor='black')
plt.title("Suno Lyrics Fidelity Distribution")
plt.xlabel("Fidelity Ratio (0-1)")
plt.ylabel("Number of Songs")
plt.grid(axis='y', alpha=0.75)
plt.show()

# 8. 可視化: Style別平均Fidelity
style_avg = df.groupby("style")["fidelity_ratio"].mean().sort_values(ascending=False)
style_avg.plot(kind="bar", figsize=(10,5), color="lightgreen", edgecolor="black")
plt.title("Average Fidelity Ratio by Style")
plt.ylabel("Average Fidelity (0-1)")
plt.xlabel("Style")
plt.grid(axis='y', alpha=0.75)
plt.show()

■ このコードでできること

  1. 歌詞忠実度を 0~1 の数値 で算出

    • 1.0 → 完全一致

    • 0.0 → 全く違う / インスト

  2. 全生成曲の ヒストグラムで忠実度分布 を確認

  3. Style別の 平均忠実度棒グラフ で傾向分析

  4. CSV出力で後からExcelやPythonでさらに統計解析可能

現在の方法は 文字列類似度を単純に SequenceMatcher で計算 しているため、歌詞の長さや単語の切れ目、補完・言い換えによって数値がかなり離散化します。
例えば:

  • 歌詞が短い場合 → 少し文字が違うだけで 0.7 → 0.3 など大きく変動

  • 歌詞が長い場合 → 一部違っても 0.9 前後に収束しやすい

  • インストの場合 → 0 に近い

  • 部分的に補完される → 0.2~0.6 の間に散らばる


■ 改善方法(境界値・連続性を持たせる案)

  1. 区切りごとに比較する

    • 文・フレーズ・行ごとに部分一致率を計算

    • 平均を取る → 極端な離散値を抑制

  2. 単語レベルで一致判定

    • 日本語形態素解析(MeCabなど)で単語ごとに比較

    • 0~1の連続値で忠実度を積算

  3. しきい値でラベル化

    • 例:

      • fidelity > 0.85 → Exact match

      • 0.5 < fidelity ≤ 0.85 → Partial match

      • fidelity ≤ 0.5 → Different/Instrumental

    • ヒストグラムや棒グラフで離散値を減らせる

  4. 音素レベルでの一致判定

    • Whisperや音声認識結果を かな/ローマ字音素 に変換して比較

    • 発音的に近い場合も部分一致として評価可能


要するに、今の「文字列全体のSimilarity」だけだと 長さや補完の影響でバラつきが大きくなる ので、
フレーズや単語、音素レベルで正規化した忠実度 を計算すると連続的で安定した数値になります。

フレーズ・単語レベルで忠実度を計算して、連続値として安定させるバージョンを作ります。
日本語用に MeCab で形態素解析を使い、単語ごとの一致率を平均化します。


import os
import json
import pandas as pd
import whisper
import MeCab
from difflib import SequenceMatcher
import matplotlib.pyplot as plt

# ------------------------------
# 1. Suno生成ファイルのフォルダ
# ------------------------------
base_folder = "/path/to/suno_outputs"

# ------------------------------
# 2. Whisperモデルロード
# ------------------------------
model = whisper.load_model("small")  # small, medium, large

# ------------------------------
# 3. MeCab初期化(単語分割用)
# ------------------------------
tagger = MeCab.Tagger("-Owakati")  # 分かち書き

# ------------------------------
# 4. 単語レベルの類似度計算
# ------------------------------
def word_level_similarity(original_text, recognized_text):
    """
    日本語テキストを単語に分割し、単語レベルで類似度計算
    """
    if not original_text.strip():
        return 0.0

    # 分かち書き
    original_words = tagger.parse(original_text).strip().split()
    recognized_words = tagger.parse(recognized_text).strip().split()

    # 単語ごとの一致判定
    matches = 0
    for word in original_words:
        if word in recognized_words:
            matches += 1

    return matches / max(len(original_words), 1)  # 忠実度0~1

# ------------------------------
# 5. データ抽出
# ------------------------------
data_list = []

for root, dirs, files in os.walk(base_folder):
    for file in files:
        if file.endswith(".json"):
            json_path = os.path.join(root, file)
            with open(json_path, "r", encoding="utf-8") as f:
                try:
                    meta = json.load(f)
                    filename = meta.get("filename", "").replace(".json", ".wav")
                    audio_path = os.path.join(root, filename)

                    if os.path.exists(audio_path):
                        result = model.transcribe(audio_path, language='ja')
                        recognized_text = result['text']

                        original_lyrics = meta.get("lyrics", "")
                        fidelity_ratio = word_level_similarity(original_lyrics, recognized_text)

                        data_list.append({
                            "filename": filename,
                            "original_lyrics": original_lyrics,
                            "recognized_text": recognized_text,
                            "style": meta.get("style", ""),
                            "length": meta.get("length", ""),
                            "actual_duration": meta.get("actual_duration", ""),
                            "fidelity_ratio": fidelity_ratio
                        })
                except Exception as e:
                    print(f"Error processing {json_path}: {e}")

# ------------------------------
# 6. DataFrame化
# ------------------------------
df = pd.DataFrame(data_list)

# ------------------------------
# 7. CSV出力
# ------------------------------
df.to_csv("suno_lyrics_fidelity_wordlevel.csv", index=False, encoding="utf-8-sig")

# ------------------------------
# 8. 可視化: Fidelityヒストグラム
# ------------------------------
plt.figure(figsize=(8,5))
plt.hist(df['fidelity_ratio'], bins=10, color='skyblue', edgecolor='black')
plt.title("Suno Lyrics Fidelity Distribution (Word Level)")
plt.xlabel("Fidelity Ratio (0-1)")
plt.ylabel("Number of Songs")
plt.grid(axis='y', alpha=0.75)
plt.show()

# ------------------------------
# 9. 可視化: Style別平均Fidelity
# ------------------------------
style_avg = df.groupby("style")["fidelity_ratio"].mean().sort_values(ascending=False)
style_avg.plot(kind="bar", figsize=(10,5), color="lightgreen", edgecolor="black")
plt.title("Average Fidelity Ratio by Style (Word Level)")
plt.ylabel("Average Fidelity (0-1)")
plt.xlabel("Style")
plt.grid(axis='y', alpha=0.75)
plt.show()

■ 改善ポイント

  1. 文字列全体ではなく単語レベルで比較 → 長さの影響を減らす

  2. 忠実度を連続値(0~1)で計算 → 離散値が少なくなる

  3. 部分一致も反映 → インスト化されず一部歌われた場合でも0.0にはならない

  4. CSV出力+グラフで生成パターンごとの傾向を可視化可能

数字の表記別(アラビア数字 vs 漢字 vs ひらがな)や桁数別で、歌詞忠実度の傾向を可視化できるように拡張します。

今回は以下の流れです:

  1. 歌詞中の数字を抽出

  2. 表記ごとに分類(アラビア数字、漢字、ひらがな)

  3. 桁数ごとに忠実度平均を計算

  4. 可視化(棒グラフ・散布図)


import re
import pandas as pd
import matplotlib.pyplot as plt

# ------------------------------
# 1. 既存の忠実度データ読み込み
# ------------------------------
df = pd.read_csv("suno_lyrics_fidelity_wordlevel.csv", encoding="utf-8-sig")

# ------------------------------
# 2. 数字抽出用関数
# ------------------------------
def extract_numbers(text):
    """
    歌詞から数字を抽出
    return: list of tuples (number_string, type)
    type: 'arabic', 'kanji', 'hiragana'
    """
    results = []

    # アラビア数字
    for match in re.findall(r'\d+', text):
        results.append((match, 'arabic'))

    # 漢数字(簡単な0~9999までの漢数字に対応)
    kanji_pattern = r'[一二三四五六七八九十百千万億]+'
    for match in re.findall(kanji_pattern, text):
        results.append((match, 'kanji'))

    # ひらがな数字(例:ひとつ、ふたつなど)簡易版
    hiragana_pattern = r'ひとつ|ふたつ|みっつ|よっつ|いつつ|むっつ|ななつ|やっつ|ここのつ|とお'
    for match in re.findall(hiragana_pattern, text):
        results.append((match, 'hiragana'))

    return results

# ------------------------------
# 3. 数字別・桁数別の忠実度集計
# ------------------------------
records = []

for idx, row in df.iterrows():
    original_text = row['original_lyrics']
    fidelity = row['fidelity_ratio']
    numbers = extract_numbers(original_text)

    for num_str, num_type in numbers:
        length = len(num_str) if num_type != 'hiragana' else 1  # ひらがな数字は1桁扱い
        records.append({
            "filename": row['filename'],
            "number_str": num_str,
            "number_type": num_type,
            "digit_length": length,
            "fidelity_ratio": fidelity
        })

num_df = pd.DataFrame(records)

# ------------------------------
# 4. 桁数別・タイプ別平均忠実度
# ------------------------------
summary = num_df.groupby(['number_type','digit_length'])['fidelity_ratio'].mean().reset_index()

# ------------------------------
# 5. 可視化
# ------------------------------
plt.figure(figsize=(10,6))

for num_type in ['arabic', 'kanji', 'hiragana']:
    subset = summary[summary['number_type']==num_type]
    plt.plot(subset['digit_length'], subset['fidelity_ratio'], marker='o', label=num_type)

plt.title("Number Type & Digit Length vs Lyrics Fidelity")
plt.xlabel("Digit Length")
plt.ylabel("Average Fidelity Ratio")
plt.grid(True)
plt.legend()
plt.show()

# ------------------------------
# 6. 桁数ごとの散布図(個別曲)
# ------------------------------
plt.figure(figsize=(10,6))
colors = {'arabic':'blue','kanji':'green','hiragana':'orange'}

for t in ['arabic','kanji','hiragana']:
    subset = num_df[num_df['number_type']==t]
    plt.scatter(subset['digit_length'], subset['fidelity_ratio'], alpha=0.6, color=colors[t], label=t)

plt.title("Number Type & Digit Length vs Lyrics Fidelity (Scatter)")
plt.xlabel("Digit Length")
plt.ylabel("Fidelity Ratio")
plt.grid(True)
plt.legend()
plt.show()

■ この拡張でできること

  1. 数字の表記タイプ別の忠実度傾向 を確認

    • アラビア数字は桁数が増えると忠実度が低下するか

    • 漢数字やひらがなはどう反応するか

  2. 桁数ごとの傾向 が分かる → 長い数字は認識されにくい

  3. 散布図で個別曲レベルの傾向も可視化可能


💡 応用アイデア

  • 数字だけでなく 特定単語や記号の忠実度傾向 も同様の手法で可視化可能

  • 複数回生成の結果と組み合わせて 確率的挙動の分析 もできる

Pythonなどで行う分析は基本的に 「生成済みファイルや出力結果を後処理」 する形なので、SunoやChatGPTの内部処理やリアルタイムの意思決定過程は直接観測できません。

言い換えると、Pythonでできるのは

  • 出力結果(音声、歌詞、メタデータ)から 統計・傾向・忠実度 を算出

  • 桁数や単語の頻度など 特徴量の相関 を推定

  • 複数生成の平均や分散、散布図による 挙動のパターン化

ですが、生成の瞬間に内部で何がどう確率的に選ばれているか は外からは見えません。

つまり、あなたがnoteで30回以上投稿したような 十分な母集団がある場合は、統計的傾向はほぼ確定 できますが、個々の生成プロセスの「なぜその単語やフレーズが選ばれたか」は推察の域を出ません。

言うなれば、CAEの実証実験と同じで、「現象は観測できるが内部の微細な決定過程はブラックボックス」 という状態です。

定量化は「観測可能な出力」から平均・分散・傾向などを算出するので、母集団が十分に大きければかなり信頼性のある結論が出せます。

しかし 定性化、つまり「なぜその出力が生まれたか」「生成プロセスの本質的な因果」を解釈する段階になると、一気に不確実性が増します。

理由は以下です:

  1. 因子や変数の把握が不完全

    • 数字の桁数、漢字・ひらがな・アラビア数字の違い

    • 文脈依存性や韻、アクセントの影響

    • 内部の確率的選択やモデルの微調整(temperature、top_pなど)

  2. ブラックボックス性

    • AIモデル内部のパラメータは数十億〜数千億単位

    • 外部から観測できるのは最終出力だけ

  3. プログラミング裁量

    • データ抽出や指標化の方法次第で、見える傾向が全く変わる

    • どの因子を取り出すか、どの粒度で分析するかは分析者の判断に依存

つまり、定量化は「観測可能な現象」を客観的にまとめることができるが、定性化は分析者のセンス・仮説・モデル化能力に大きく左右される ということです。

あなたのように、実験屋の経験で「どこで飽和するか」「挙動の違和感」を直感的に見抜く力があると、定性化もある程度信頼できる形で整理できますが、完全な客観性は保証できません。

タグ

#Suno #AI音楽生成 #日本語音楽 #文脈依存 #感情タグ #実験音楽 #作曲家融合 #渡辺宙明 #小林亜星 #すぎやまこういち #音楽生成 #脳的演奏

いいなと思ったら応援しよう!