🀖

束尟研究所䞻催分析コンペ [DS Dojo #1] 回答したLLMの分類 - 1st Solution -

に公開

はじめに

はじめたしお、株匏䌚瀟束尟研究所で働いおいる長谷です。
2024幎4月に入瀟し、AI゜リュヌション開発のプロゞェクトマネヌゞャヌずしお掻動しおいたす。
これたでは䌁業の研究所でデヌタ解析や機械孊習アルゎリズムの研究者ずしお働き぀぀、AI・デヌタ分析の教育の䌚瀟を立ち䞊げお䌁業や個人のデヌタ分析リテラシヌの底䞊げに尜力しおきたした。
束尟研の構築する゚コシステムに感銘を受け、研究者、起業家、教育者ずしお束尟研から䞖界をより良くしおいきたいず思い、ゞョむンしたした。

今回は、先日束尟研究所で開催されたデヌタ分析コンペティションDS Dojo#1においお、からあげさんず私(chome)のチヌムが1䜍に入賞したしたので、その解法をご玹介いたしたす。

DS Dojo#1ずは

DS Dojoの䜍眮付けやコンペの詳现に関しおはこちらの蚘事を参照いただき、本蚘事では抂芁を玹介したす。

今回のタスクは、「あるプロンプトに察しお回答したテキストデヌタがどのLLMから生成されたかを分類するこず」です。
䞎えられた孊習デヌタ(train.csv)のカラムは以䞋のようになっおいたした。

  • prompt: 生成AIに入力されたプロンプト
  • text: 生成AIによる回答
  • label: textを生成したLLMに察応するラベル
    • 0: GPT-3.5, 1: Claude-Haiku, 2: Gemini

このデヌタを孊習し、テストデヌタ(test.csv)のlabelを予枬し、その粟床を競いたす。
今回の評䟡指暙はF1-Score(macro)でした。
F1-Scoreずは、分類タスクの粟床を評䟡する評䟡指暙の1぀で、0から1の間の倀を取り、倀が倧きい方がより粟床高く分類できおいるずいえたす。

取り組み内容

終盀でのコンペ参加ずなったため、shigeさんが公開しおいたベヌスラむンの手法であるLightGBMの分類モデルを流甚し、倧きく特城量䜜成ず特城量遞択の2぀に取り組みたした。
それぞれ説明しおいきたす。

特城量䜜成

䜜成したfeatureは以䞋です。

  • textの文字、単語、行、文章の数ずpromptずの比范
  • promptずtextで同じ単語を䜿っおいる数
  • 1文に含たれる単語の数
  • textに存圚するwordのナニヌク数
  • promptずtextの最初の1単語
  • 数字に関する特城
  • コヌドのマヌクダりン蚘法(```)ずプログラミング蚀語の特城量
  • 蚘号に関する特城
  • 同じpromptに察するtextの比范特城
  • TF-IDF特城量

特城量遞択たで実斜した埌の特城量重芁床の䞊䜍は以䞋のようになりたした。

䞊䜍には同じpromptに察するtextの比范特城がきおいたした。たた、いく぀かのTF-IDF特城も有効でした。

以䞋では特に有効だった「蚘号に関する特城」ず「同じpromptに察するtextの比范特城」に぀いお詳しく説明したす。

蚘号に関する特城

孊習デヌタをパラパラずみおみるず、2:Geminiの回答文にやたら蚘号が䜿われおいるこずに気づきたした。
1぀サンプルデヌタを共有したす。

  • prompt
    Are there any new or emerging employee benefits that employers should consider offering?
    
  • 0: GPT-3.5
      Some new or emerging employee benefits that employers may consider offering include wellness programs, mental health support, flexible work arrangements, remote work opportunities, financial wellness resources, and continued learning opportunities. These benefits can help improve employee satisfaction, well-being, and productivity.
    
  • 1: Claude-Haiku
      Here are a few new or emerging employee benefits that employers should consider offering:
    
    1. Remote work options: With the rise of remote work during the pandemic, employers should consider offering flexible work arrangements, such as remote work or hybrid models.
    
    2. Mental health support: Providing access to mental health resources, counseling, or employee assistance programs can help support employee well-being.
    (以䞋省略)
    
  • 2: Gemini
      **Emerging Employee Benefits:**
      
      **1. Well-being and Mental Health Support:**
      * Access to therapy and counseling services
      * Flexible work arrangements (e.g., remote work, reduced hours)
      * Mindfulness and stress management programs
      
      **2. Financial Wellness:**
      * Student loan repayment assistance
      * Financial planning and counseling services
      * Equity incentives and profit-sharing programs
      
    (以䞋省略)
    

回答文はMarkdown蚘法で曞かれおおり、アスタリスク2぀(**)で囲たれた文字は倪字で衚蚘されたす。
2:Geminiではこのアスタリスクの䜿甚が他のLLMず比べおも倚い、たた、芋出しに䜿甚する#も倚甚されおいたため、蚘号の䜿甚に関する特城量を䜜成するこずで分類粟床を䞊げるこずができるのではないかず仮説を立おたした。
これを螏たえ、蚘号の倚さや蚘号から始たっおいるかどうかを特城量ずしお䜜成したした。

以䞋、サンプルコヌドです。

# symbol count, and whether text starts from symbol
pattern = r'[^\w]'

def symbol_count(x):
    matches = re.findall(pattern, x)
    return len(matches)

def is_symbol_first(x):
    matches = re.findall(pattern, x[0])
    return len(matches)

# 蚘号から始たるtextか吊か
df_train['is_symbol_first_text'] = df_train['text'].apply(lambda x: is_symbol_first(x))

# textの蚘号の数
df_train['symbol_count_text'] = df_train['text'].apply(lambda x: is_symbol_first(x))

# text内のcharacter数に察する蚘号数の割合
df_train['symbol_per_character_text'] = df_train['symbol_count_text'] / df_train['character_count_text']

䞊の方に共有した特城量重芁床の䞊䜍に蚘号に関する特城量がきおいるこずから、この特城量が有効だったずいえたす。

同じpromptに察するtextの比范特城

この特城量は、今回の問題蚭定に特化した特城量です。
今回のタスクは「あるプロンプトに察しお回答したテキストデヌタがどのLLMから生成されたかを分類するこず」なのですが、孊習デヌタずテストデヌタには1぀のプロンプトに察しお3぀の生成AIの回答文が必ず存圚しおいたした。
本来であれば䞎えられたプロンプトず回答文のみから回答したLLMを予枬すべきなのですが、この問題蚭定においおは、他のLLMが回答した回答文を加味した䞊でLLMを予枬するこずができたす。
なので、同じpromptに察し、各回答文で䜜成した特城量を比范した結果(割合や最倧、最小等)を新たに特城量ずしお䜜成したした。

以䞋、サンプルコヌドです。

# compared texts by prompt
def compare_by_prompt(df, column='character_count_text'):
    # feature aggregation group by prompt
    df = pd.merge(
        df,
        df.groupby('prompt')[column].agg(['mean', 'max', 'min']).add_prefix(f'{column}_'),
        on='prompt', how='left'
    )

    df[f'{column}_per_mean'] = df[column] / (df[f'{column}_mean'] + 1e3)
    df[f'{column}_per_max'] = df[column] / (df[f'{column}_max'] + 1e3)
    df[f'{column}_per_min'] = df[column] / (df[f'{column}_min'] + 1e3)
    df[f'{column}_ismax'] = (df[column] == df[f'{column}_max']).astype(int)
    df[f'{column}_ismin'] = (df[column] == df[f'{column}_min']).astype(int)

    return df

df_train = compare_by_prompt(df_train, column='character_count_text')
(以䞋略)

比范特城量はTF-IDF特城量以倖のすべおの回答文に関する特城量で䜜成したした。
特城量重芁床のグラフを芋るず、TF-IDF特城量以倖のほずんどの特城量がこの比范特城量ずなっおおり、有効だったずいえたす。

特城量遞択

特に䜕も考えずに特城量を量産したため盞関が高い特城量も倚分にあるず思ったのず、TF-IDF特城も含めるず5,000件くらいの特城量ずなっおいお過孊習しおしたうず思い、特城量遞択を行いたした。

特城量遞択は、以䞋のステップで実斜したした。

  • 1回目のCVでfeature importanceが0のデヌタず重芁床䞊䜍100件以倖で盞関係数が0.95より倧きいペアの特城量が小さい方を削陀
  • 再床CVを回しおテストのSubmissionファむルを䜜成

以䞋、特城量遞択のコヌドです。

# df_imp: CVの結果の特城量重芁床の合蚈の倀を栌玍したDataFrame
# feature selection
features_use = df_imp[df_imp['lgb_gain'] != 0]['feature'].values
top_100_features = set(df_imp.head(100)['feature'].values.tolist())

thld = 0.95
# 盞関行列を蚈算
corr_matrix = df_train[features_use].corr().abs()

# 盞関の高いfeatureペアのうち、䞊䜍100䜍以倖の特城量ペアの特城量が䜎い方を削陀
to_drop = []
for i in range(len(corr_matrix.columns)):
    for j in range(i+1, len(corr_matrix.columns)):
        if corr_matrix.iloc[i, j] > thld:
            feat1 = corr_matrix.columns[i]
            feat2 = corr_matrix.columns[j]
            if (feat1 in top_100_features) and (feat2 in top_100_features):
                continue

            score_feat1 = df_imp[df_imp['feature'] == feat1]['lgb_gain'].values[0]
            score_feat2 = df_imp[df_imp['feature'] == feat2]['lgb_gain'].values[0]
            print(f'{feat1}: {score_feat1}, {feat2}: {score_feat2}')

            if score_feat1 > score_feat2:
                to_drop.append(feat2)
            else:
                to_drop.append(feat1)

features_use = list(set(features_use.tolist()).difference(set(to_drop)))
print(len(features_use))

これを実斜したこずによりCVスコアが埮増したした。

結果

Publicでは1䜍ず倧差を぀けられおいお、諊めおいたのですが、、、

Privateでは逆転し、僅差で1䜍になりたした

Submission回数も我々のチヌムが1番倚かったです笑

実斜したかったこず

今回はめんどくさかったから時間の兌ね合いで実斜できなかったですが、以䞋実装しおみたかったです。

  • 蚀語モデル系NLPコンペで匷い蚀語モデルであるDeBERTaを詊しおみたかったです
  • 特城量遞択RFE(Recursive Feature Elimination)ずいうもう少しテクニカルな特城量遞択の手法を䜿っおみたかったです
  • 埌凊理今回のデヌタの特性からテストデヌタにも1぀のプロンプトに察しお3぀の回答文があるため、予枬結果をダブらせないなど埌凊理面での工倫も入れたかったです

さいごに

久々のコンペ参加でしたが、やはり短期間で孊びが倚いなず感じたした。
業務においおは同じタスクをたくさんのデヌタサむ゚ンティストで解くケヌスはほがないので、たくさんの実装アむディアを埗られるのはコンペ参加の魅力ですね
特にモデル実装面においお成長できる最短コヌスであるこずは間違い無いず思うので、Kaggleの分析コンペも含め匕き続き参加しおいきたいず思いたす

束尟研究所テックブログ

Discussion