KiliとHuggingFace AutoTrainを使用した意見分類

'Opinion Classification using Kili and HuggingFace AutoTrain'

イントロダクション

ユーザーのニーズを理解することは、ユーザーに関連するビジネスにおいて重要です。しかし、それには多くの労力と分析が必要であり、非常に高価です。ならば、Machine Learningを活用しませんか?Auto MLを使用することでコーディングを大幅に削減できます。

この記事では、HuggingFace AutoTrainとKiliを活用して、テキスト分類のためのアクティブラーニングパイプラインを構築します。Kiliは、品質の高いトレーニングデータ作成を通じて、データ中心のアプローチを強力にサポートするプラットフォームです。協力的なデータ注釈ツールとAPIを提供し、信頼性のあるデータセット構築とモデルトレーニングの素早い反復を可能にします。アクティブラーニングとは、データセットにラベル付けされたデータを追加し、モデルを反復的に再トレーニングするプロセスです。そのため、終わりのない作業であり、人間がデータにラベルを付ける必要があります。

この記事の具体的なユースケースとして、Google PlayストアのVoAGIのユーザーレビューを使用してパイプラインを構築します。その後、構築したパイプラインでレビューをカテゴリ分類します。最後に、分類されたレビューに感情分析を適用します。その結果を分析することで、ユーザーのニーズと満足度を理解することが容易になります。

HuggingFaceを使用したAutoTrain

自動化されたMachine Learningは、Machine Learningパイプラインの自動化を指す用語です。データクリーニング、モデル選択、ハイパーパラメータの最適化も含まれます。🤗 transformersを使用して自動的にハイパーパラメータの検索を行うことができます。ハイパーパラメータの最適化は困難で時間のかかるプロセスです。

transformersや他の強力なAPIを使用してパイプラインを自分自身で構築することもできますが、AutoTrainを完全に自動化することも可能です。AutoTrainは、transformers、datasets、inference-apiなどの多くの強力なAPIを基に構築されています。

データのクリーニング、モデルの選択、ハイパーパラメータの最適化のステップは、すべてAutoTrainで完全に自動化されています。このフレームワークをフルに活用することで、特定のタスクに対してプロダクションレディのSOTAトランスフォーマーモデルを構築することができます。現在、AutoTrainはバイナリとマルチラベルのテキスト分類、トークン分類、抽出型質問応答、テキスト要約、テキストスコアリングをサポートしています。また、英語、ドイツ語、フランス語、スペイン語、フィンランド語、スウェーデン語、ヒンディー語、オランダ語など、多くの言語もサポートしています。AutoTrainでサポートされていない言語の場合、カスタムモデルとカスタムトークナイザを使用することも可能です。

Kili

Kiliは、データ中心のビジネス向けのエンドツーエンドのAIトレーニングプラットフォームです。Kiliは、最適化されたラベリング機能と品質管理ツールを提供し、データを管理するための便利な手段を提供します。画像、ビデオ、テキスト、PDF、音声データを素早く注釈付けできます。GraphQLとPythonの強力なAPIも備えており、データ管理を容易にします。

オンラインまたはオンプレミスで利用可能であり、コンピュータビジョンやNLP、OCRにおいてモダンなMachine Learning技術を実現することができます。テキスト分類、固有表現認識(NER)、関係抽出などのNLP / OCRタスクをサポートしています。また、オブジェクト検出、画像転写、ビデオ分類、セマンティックセグメンテーションなどのコンピュータビジョンタスクもサポートしています。

Kiliは商用ツールですが、Kiliのツールを試すために無料のデベロッパーアカウントを作成することもできます。料金については、価格ページから詳細を確認できます。

プロジェクト

モバイルアプリケーションについての洞察を得るために、レビューの分類と感情分析の例を取り上げます。

Google PlayストアのVoAGIのレビュー約4万件を抽出しました。このデータセットのレビューテキストをステップバイステップで注釈付けし、レビュー分類のためのパイプラインを構築します。モデリングでは、最初のモデルはAutoTrainを使用して準備します。その後、AutoTrainを使用せずにモデルを構築します。

すべてのコードとデータセットは、プロジェクトのGitHubリポジトリで見つけることができます。

データセット

まず、生のデータセットを見てみましょう。

このデータセットには10の列と40130のサンプルがあります。必要なのはcontentという列で、これがユーザーのレビューです。始める前に、いくつかのカテゴリを定義する必要があります。

4つのカテゴリを定義しました。

  • サブスクリプション:VoAGIにはサブスクリプションオプションがあるため、サブスクリプション機能に関するユーザーの意見はここに属します。
  • コンテンツ:VoAGIは共有プラットフォームであり、詩から高度な人工知能研究まで様々な執筆物があります。ユーザーの意見はさまざまなトピックやコンテンツの品質に関連するものがここに属します。
  • インターフェース:UIに関する意見、記事の検索、推薦エンジン、およびインターフェースに関連するすべての内容がここに属します。これには支払いに関連する問題も含まれます。
  • ユーザーエクスペリエンス:アプリケーションに関するユーザーの一般的な意見や考えが含まれます。他のカテゴリを示さない抽象的なものであるべきです。

ラベリングの部分では、まず最初にKiliのプラットフォームでプロジェクトを作成する必要があります。プラットフォームのウェブインターフェースまたはAPIのどちらを使用しても構いません。両方を見てみましょう。

ウェブインターフェースから:

プロジェクト一覧ページから、マルチクラスのテキスト分類プロジェクトを作成します。

その後、プロジェクトのページで、[アセットの追加]ボタンをクリックしてデータを追加できます。現在は最大で25000サンプルを追加できますが、Kiliの営業チームに連絡することでこの制限を拡張することもできます。

プロジェクトを作成した後、ジョブを追加する必要があります。設定ページからラベリングインターフェースを準備することができます。

4つのカテゴリを定義しているにもかかわらず、複数のカテゴリが必要なレビューや完全に奇妙なカテゴリに出くわすことは避けられません。これらのケースをキャッチするために、2つのラベル(モデリングに使用しない)を追加します。

この例では、2つの追加のラベル(その他、マルチラベル)を追加しました。また、ラベリング時にラベルを決定する方法を示すために、固有表現認識(NER)のジョブも追加しました。最終的なインターフェースは以下のように表示されます。

左側のメニューからわかるように、ラベルに関する説明を示すリンクを[Instructions]ページに追加することも可能です。[Members]から他のメンバーをプロジェクトに追加したり、[Quality management]ページから品質管理を追加することもできます。詳細はドキュメントを参照してください。

次に、Python APIを使用してプロジェクトを作成しましょう:

まず、必要なライブラリをインポートする必要があります。

( notebooks/kili_project_management.ipynb )

import os
# データを処理するために使用する
import pandas as pd

# APIクライアント
from kili.client import Kili
# 進捗状況を表示するためのプログレスバー
from tqdm import tqdm

from dotenv import load_dotenv
load_dotenv()

プラットフォームにアクセスするために、クライアントを認証する必要があります。

API_KEY = os.getenv('KILI_API_KEY')
# Kiliクライアントを初期化および認証する
kili = Kili(api_key = API_KEY)

これでインターフェースの準備を始めることができます。インターフェースはPythonの辞書です。ジョブを定義し、ラベルを埋めることになります。すべてのラベルには子ラベルも存在する可能性があるため、ラベルも辞書として渡します。

labels = ['ユーザーエクスペリエンス', '購読', 'コンテンツ', 'その他', '複数ラベル']
entity_dict = {
    'ユーザーエクスペリエンス': '#cc4125',
    '購読': '#4543e6',
    'コンテンツ': '#3edeb6',
}
project_name = 'トピック分類のためのユーザーレビューデータセット'
project_description = "VoAGIのGoogle Playストアから取得したアプリのレビューをトピック分類するためのデータセット"

interface = {
    'jobs': {
        'JOB_0': {
            'mlTask': 'CLASSIFICATION',
            'instruction': 'ラベル',
            'required': 1,
            'content': {
                "categories": {},
                "input": "radio",
            },
        },
        'JOB_1': {
            'mlTask': "NAMED_ENTITIES_RECOGNITION",
            'instruction': 'エンティティ',
            'required': 1,
            'content': {
                'categories': {},
                "input": "radio"
            },
        },
    }
}

# ジョブをインターフェースのJSONで埋める
for label in labels:
    # ラベルを大文字に変換し、ホワイトスペースをアンダースコア(_)に置き換えます
    # 例:ユーザーエクスペリエンス -> USER_EXPERIENCE
    # これはインターフェースを埋めるための推奨される方法です
    label_upper = label.strip().upper().replace(' ', '_')
    # 
    content_dict_0 = interface['jobs']['JOB_0']['content']
    categories_0 = content_dict_0['categories']
    category = {'name': label, 'children': []}
    categories_0[label_upper] = category

for label, color in entity_dict.items():
    label_upper = label.strip().upper().replace(' ', '_')
    content_dict_1 = interface['jobs']['JOB_1']['content']
    categories_1 = content_dict_1['categories']
    category = {'name': label, 'children': [], 'color': color}
    categories_1[label_upper] = category

# これでプロジェクトを作成できます
# このメソッドは作成されたプロジェクトのIDを返します
project_id = kili.create_project(json_interface=interface,
                            input_type='TEXT',
                            title=project_name,
                            description=project_description)['id']

プロジェクトにデータをアップロードする準備が整いました。 append_many_to_datasetメソッドを使用してデータをプラットフォームにインポートすることができます。Python APIを使用することで、最大100件のバッチでデータをインポートすることができます。以下にデータをアップロードするための簡単な関数があります:

def import_dataframe(project_id:str, dataset:pd.DataFrame, text_data_column:str, external_id_column:str, subset_size:int=100) -> bool:
    """
    引数:
    入力
        - project_id (str): データを読み込むプロジェクトを指定します。プロジェクトを作成した際にも返されます
        - dataset (pandas DataFrame): idとテキスト入力のための適切な列を持つデータセット
        - text_data_column (str): テキスト入力データが含まれる列を指定します
        - external_id_column (str): idが含まれる列を指定します
        - subset_size (int): 一度にインポートするサンプル数を指定します。100より大きい値にはできません
    
    出力:
        None
    
    戻り値: 
        処理の成功に関するTrueまたはFalse

    """

    assert subset_size <= 100, "Kiliではアプリに一度にアップロードできるアセットは最大100個です"


    L = len(dataset)

    # アップロード制限として25000を設定していますが、変更することもできます
    if L>25000:
        print('Kili Projectsは現在、デフォルトで最大25000サンプルをサポートしています。最初の25000サンプルをインポートしています...')
        L=25000

    i = 0

    while i+subset_size < L:
        
        subset = dataset.iloc[i:i+subset_size]

        externalIds = subset[external_id_column].astype(str).to_list()
        contents = subset[text_data_column].astype(str).to_list()
        
        kili.append_many_to_dataset(project_id=project_id,
                                    content_array=contents,
                                    external_id_array=externalIds)

        i += subset_size

    return True

この関数は、与えられたdataset DataFrameをproject_idで指定されたプロジェクトにインポートするだけです。

docstringから引数を確認できます。単にデータセットを対応する列名とともに渡す必要があります。データをロードする際に取得したサンプルインデックスを使用するだけです。そして、アップロードは完了です!

dataset_path = '../data/processed/lowercase_cleaned_dataset.csv'
df = pd.read_csv(dataset_path).reset_index() # インデックスをリセットしてインデックスを取得

import_dataframe(project_id, df, 'content', 'index')

Python APIを使用するのは難しくありませんでした。使用したヘルパーメソッドで多くの困難をカバーしています。データセットを更新した際に新しいサンプルを確認するために別のスクリプトも使用しました。データセットの更新後にモデルのパフォーマンスが低下することがあります。これは、誤ったラベル付けやデータセットへのバイアスの導入など、単純なミスに起因するものです。スクリプトは単に認証し、指定された2つのデータセットバージョンの異なるサンプルをTo Reviewに移動します。サンプルのプロパティはupdate_properties_in_assetsメソッドを使用して変更することができます:

( scripts/move_diff_to_review.py )

# Kiliクライアントと引数のセットアップ
from kili.client import Kili
from dotenv import load_dotenv
import os
import argparse

import pandas as pd

load_dotenv()

parser = argparse.ArgumentParser()
parser.add_argument('--first',
                    required=True,
                    type=str,
                    help='最初のデータフレームへのパス')
parser.add_argument('--second',
                    required=True,
                    type=str,
                    help='2番目のデータフレームへのパス')

args = vars(parser.parse_args())

# Kili接続の設定
API_KEY = os.getenv('KILI_API_KEY')
kili = Kili(API_KEY)

# データフレームの読み込み
df1 = pd.read_csv(args['first'])
df2 = pd.read_csv(args['second'])

# 二つのデータフレームを連結させることで共通の要素の重複を持つことができる
# その後、重複した要素を削除して異なる要素のみを取得することができます
diff_df = pd.concat((df1, df2)).drop_duplicates(keep=False)
diff_ids = diff_df['id'].to_list()

# 変更は、各サンプルに対する変更が含まれる配列として与える必要があります
# そのため、status_array引数には [‘TO_REVIEW’] * len(diff_df) が渡されます
kili.update_properties_in_assets(diff_ids,
                                 status_array=['TO_REVIEW'] * len(diff_ids))

print('レビューするために%dエントリを設定しました!' % len(diff_df))

ラベリング

ソースデータをアップロードしたので、プラットフォームには使いやすい組み込みのラベリングインターフェースがあります。利用可能なキーボードショートカットはデータの注釈付けの際に役立ちました。簡単にインターフェースを使用し、自動的に定義されたショートカットを使用することで、ラベリングを簡素化しました。ショートカットは、インターフェースの右上にあるキーボードアイコンをクリックすることで表示され、ラベリングインターフェース内では下線付きの文字で表示されます。

いくつかのサンプルは非常に奇妙でしたので、ラベリングをスキップすることにしました。一般的には、Kiliの組み込みプラットフォームのおかげで、プロセスははるかに簡単でした。

ラベル付けされたデータのエクスポート

Python APIを使用して、ラベル付けされたデータを簡単にエクスポートすることができます。以下のスクリプトは、ラベル付けおよびレビュー済みのサンプルをデータフレームにエクスポートし、指定した名前でCSVファイルとして保存します。

( scripts/prepare_dataset.py )

import argparse
import os

import pandas as pd
from dotenv import load_dotenv
from kili.client import Kili

load_dotenv()

parser = argparse.ArgumentParser()
parser.add_argument('--output_name',
                    required=True,
                    type=str,
                    default='dataset.csv')
parser.add_argument('--remove', required=False, type=str)
args = vars(parser.parse_args())

API_KEY = os.getenv('KILI_API_KEY')
dataset_path = '../data/processed/lowercase_cleaned_dataset.csv'
output_path = os.path.join('../data/processed', args['output_name'])


def extract_labels(labels_dict):
    response = labels_dict[-1]  # 最新バージョンのサンプルを選択
    label_job_dict = response['jsonResponse']['JOB_0']
    categories = label_job_dict['categories']
    # すべてのサンプルはラベルを持っているため、インデックスで選択するだけです
    label = categories[0]['name']
    return label


kili = Kili(API_KEY)
print('認証済みです!')
# クエリは一致した要素(この場合はプロジェクト)を含むリストを返します
# この名前のプロジェクトは1つしかないため、最初のインデックスを選択できます
project = kili.projects(
    search_query='トピック分類のためのユーザーレビューデータセット')[0]
project_id = project['id']

# 返されるフィールドをカスタマイズできます
# 以下のフィールドは十分です
# labels.jsonResponseにはラベリングデータが含まれています
returned_fields = [
    'id', 'externalId', 'labels.jsonResponse', 'skipped', 'status'
]
# サンプルを外部IDで一致させるために生のデータセットも読み込みます
dataset = pd.read_csv(dataset_path)

# データフレームとしてデータを取得できます
df = kili.assets(project_id=project_id,
                 status_in=['LABELED', 'REVIEWED'],
                 fields=returned_fields,
                 format='pandas')

print('サンプルを取得しました!')

# スキップされたサンプルを渡します
df_ns = df[~df['skipped']].copy()

# ラベル付けされたサンプルを抽出します
df_ns.loc[:, 'label'] = df_ns['labels'].apply(extract_labels)
# externalId列は文字列として返されるため、整数に変換します
# インデックスとして使用するためです
df_ns.loc[:, 'content'] = dataset.loc[df_ns.externalId.astype(int), 'content']

# `labels`列を削除できます
df_ns = df_ns.drop(columns=['labels'])

# マルチラベルのサンプルも削除します
df_ns = df_ns[df_ns['label'] != 'MULTI_LABEL'].copy()

# remove引数で指定されたラベルのサンプルも削除します(指定されている場合)
if args['remove']:
    df_ns = df_ns.drop(index=df_ns[df_ns['label'] == args['remove']].index)

print('データの取得が完了しました')
print('データセットには %d のサンプルがあります' % (len(df_ns)))
print('処理済みのデータセットを保存します: %s' % os.path.abspath(output_path))

df_ns.to_csv(output_path, index=False)

print('完了!')

素晴らしいです!これでラベル付けされたデータがCSVファイルとして手に入りました。HuggingFaceでデータセットリポジトリを作成し、データをアップロードしましょう!

とても簡単です。プロフィール画像をクリックし、New Datasetを選択してください。

次に、リポジトリの名前を入力し、必要に応じてライセンスを選択して完了です!

これで、Files and versionsタブのAdd fileからデータセットをアップロードできます。

データをアップロードすると、データセットビューアが自動的に利用可能になり、サンプルを簡単に確認できます!

また、datasetsパッケージを使用してデータセットをHugging Faceのデータセットハブにアップロードすることも可能です。

モデリング

アクティブラーニングを使用しましょう。モデルに対して反復的にラベルを付けて微調整します。各反復では、データセット内の50のサンプルにラベルを付けます。サンプルの数は以下の通りです:

まず、AutoTrainを試してみましょう:

まず、AutoTrainを開きます

  1. プロジェクトを作成します

  1. 以前に作成したデータセットリポジトリを選択するか、データセットを再度アップロードすることができます。その後、分割タイプを選択する必要がありますが、自動にしておきます。

  1. モデルをトレーニングします

AutoTrainはさまざまなモデルを試し、最適なモデルを選択します。また、ハイパーパラメータの最適化も自動的に行います。データセットも自動的に処理されます。

価格は完全に使用用途に依存します。$10以下であることもありますし、現在の値よりも高価になることもあります。

トレーニングは約20分で完了し、結果はかなり良好です!

最良のモデルの精度はほぼ89%です。

これでこのモデルを使用して分析を行うことができますが、全体の設定には約30分かかりました。

AutoTrainなしのモデリング

Ray TuneとHugging FaceのTrainer APIを使用して、事前学習済みのディープラーニングモデルのハイパーパラメータを検索し、微調整を行います。私たちは、ツイートでトレーニングされたroBERTaベースの感情分類モデルを選択しました。モデルはgoogleの共同研究所で微調整され、GitHubリポジトリのnotebooksフォルダにあります。

Ray Tuneは、ハイパーパラメータの最適化のための人気のあるライブラリであり、多くのSOTAアルゴリズムがデフォルトで提供されています。OptunaやSigOptも使用することができます。スケジューラと検索アルゴリズムには、Async Successive Halving Algorithm(ASHA)とHyperOptを使用しましたが、これはほぼ出発点です。異なるスケジューラと検索アルゴリズムを使用することもできます。

何をしますか?

  • 必要なライブラリをインポートします(数十個)
  • データセットクラスを準備します
  • データを処理するための必要な関数とメソッドを定義します
  • 事前学習済みモデルとトークナイザをロードします
  • ハイパーパラメータの検索を実行します
  • 最良の結果を使用して評価を行います

まずは、必要なライブラリをインポートしましょう!(すべてのコードはnotebooks/modeling.ipynbとgoogleの共同研究所のノートブックにあります)

# 一般的なデータサイエンス/利用/可視化のインポート
import json
import os
import random

# 進捗バー
from tqdm import tqdm

# データ操作/読み取り
import numpy as np
import pandas as pd

# 可視化
import plotly.express as px
import matplotlib.pyplot as plt

# 事前定義された評価指標
from sklearn.metrics import (accuracy_score, f1_score,
                             precision_score, recall_score)

from sklearn.model_selection import train_test_split
# torchのインポート
import torch
import torch.nn as nn
from torch.utils.data import DataLoader, Dataset, random_split
# huggingfaceのインポート
import transformers
from datasets import load_metric
from transformers import (AutoModelForSequenceClassification, AutoTokenizer, 
                          Trainer, TrainingArguments)

# ハイパーパラメータの最適化のためのray tuneのインポート
from ray.tune.schedulers import ASHAScheduler, PopulationBasedTraining
from ray.tune.suggest.hyperopt import HyperOptSearch

再現性のために使用するライブラリにシードを設定します

def seed_all(seed):
    torch.manual_seed(seed)
    random.seed(seed)
    np.random.seed(seed)

SEED=42
seed_all(SEED)

さて、データセットクラスを定義しましょう!

class TextClassificationDataset(Dataset):
    def __init__(self, dataframe):
        self.labels = dataframe.label.to_list()
        self.inputs = dataframe.content.to_list()
        self.labels_to_idx = {k:v for k,v in labels_dict.items()} # labels_dictの辞書をコピーします

    def __len__(self):
        return len(self.inputs)

    def __getitem__(self, idx):
        if type(idx)==torch.Tensor:
            idx = list(idx)

        input_data = self.inputs[idx]
        target = self.labels[idx]
        target = self.labels_to_idx[target]

        return {'text': input_data, 'label':target}

HuggingFaceハブリポジトリを指定してモデルを簡単にダウンロードすることができます。指定したモデルのトークナイザもインポートする必要があります。ハイパーパラメータの最適化中にモデルを初期化するための関数を提供する必要があります。モデルはそこで定義されます。

最適化するメトリックは正確性です。この値をできるだけ高くしたいです。そのため、メトリックを読み込み、予測を取得し、好ましいメトリックを計算するための関数を定義する必要があります。

model_name = 'cardiffnlp/twitter-roberta-base-sentiment'
# モデルの正確性を最適化するために検索を実行します。
# 最初のステップとして正確性メトリックを指定して読み込む必要があります
metric = load_metric("accuracy")


# モデル名を入力したので、トークナイザを読み込むことができます
# モデルも読み込むことができますが、モデルの初期化方法はmodel_init関数で説明します。
tokenizer = AutoTokenizer.from_pretrained(model_name)


def model_init():
    """
    ハイパーパラメータの最適化は新たに初期化されたモデルによって行われるため、
    すべての検索実行のためにモデルを再初期化する必要があります。 
    この関数は、`model_name`で選択された事前学習モデルを初期化して返します。
    """
    return AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=4, return_dict=True, ignore_mismatched_sizes=True)

# 正確性を計算する関数
def compute_metrics(eval_pred):
    logits, labels = eval_pred
    predictions = np.argmax(logits, axis=-1) # 最大値を持つインデックスを選択します
    return metric.compute(predictions=predictions, references=labels)

メトリックの計算とモデルの初期化関数を定義した後、データを読み込むことができます:

file_name = "dataset-11.csv"

dataset_path = os.path.join('data/processed', file_name)
dataset = pd.read_csv(dataset_path)

また、ラベルをインデックスにマッピングするための2つの辞書も定義しました。

idx_to_label = dict(enumerate(dataset.label.unique()))
labels_dict = {v:k for k,v in idx_to_label.items()}

さて、ハイパーパラメータの検索アルゴリズムとスケジューラを定義することができます。

scheduler =  ASHAScheduler(metric='objective', mode='max')
search_algorithm = HyperOptSearch(metric='objective', mode='max', random_state_seed=SEED)
# パラメータの検索回数
n_trials =  40

モデルに渡す前にテキストデータをトークン化する必要もあります。ロードされたトークナイザを使用して簡単に行うことができます。 Ray Tuneはブラックボックス設定で動作するため、トークナイザをデフォルト引数として使用しました。さもなければ、トークナイザの定義に関するエラーが発生します。

def tokenize(sample, tokenizer=tokenizer):
    tokenized_sample = tokenizer(sample['text'], padding=True, truncation=True)
    tokenized_sample['label'] = sample['label']
    return tokenized_sample

他のユーティリティ関数として、層別化されたトークン化されたTorchデータセットの分割結果を返す関数も定義しました:

def prepare_datasets(dataset_df, test_size=.2, val_size=.2):
    train_set, test_set = train_test_split(dataset_df, test_size=test_size,
                                        stratify=dataset_df.label, random_state=SEED)

    train_set, val_set = train_test_split(train_set, test_size=val_size,
                                        stratify=train_set.label, random_state=SEED)

    # データフレームを事前にシャッフルする
    train_set = train_set.sample(frac=1, random_state=SEED)
    val_set = val_set.sample(frac=1, random_state=SEED)
    test_set = test_set.sample(frac=1, random_state=SEED)

    # データフレームをTorchデータセットに変換する
    train_dataset = TextClassificationDataset(train_set)
    val_dataset = TextClassificationDataset(val_set)
    test_dataset = TextClassificationDataset(test_set)

    # データセットをトークン化する
    tokenized_train_set = train_dataset.map(tokenize)
    tokenized_val_set = val_dataset.map(tokenize)
    tokenized_test_set = test_dataset.map(tokenize)

    # 最終的なデータセットを返す
    return tokenized_train_set, tokenized_val_set, tokenized_test_set

さて、検索を実行する準備ができました!まずはデータの前処理から始めましょう:

tokenized_train_set, tokenized_val_set, tokenized_test_set = prepare_datasets(dataset)

training_args = TrainingArguments(
    'trial_results',
    evaluation_strategy="steps",
    disable_tqdm=True,
    skip_memory_metrics=True,
)

trainer = Trainer(
    args=training_args,
    tokenizer=tokenizer,
    train_dataset=tokenized_train_set,
    eval_dataset=tokenized_val_set,
    model_init=model_init,
    compute_metrics=compute_metrics
    )

best_run = trainer.hyperparameter_search(
    direction="maximize", 
    n_trials=n_trials,
    backend="ray",
    search_alg=search_algorithm,
    scheduler=scheduler
    )

20回と40回の試行で検索を行い、以下に結果を示します。20回の実行に対するF1、再現率、適合率の重み付き平均。

40回の実行に対するF1、再現率、適合率の重み付き平均。

パフォーマンスは第3のデータセットバージョンで急上昇しました。データラベリングの一部において、誤ってデータセットにバイアスを加えました。後にサンプル分散が増加したことから、パフォーマンスはより理にかなっています。最終モデルはGoogle Driveに保存され、こちらからダウンロードすることができます。また、download_models.pyスクリプトを使用してダウンロードすることも可能です。

最終分析

今、私たちは微調整されたモデルを使用して最終分析を行うことができます。する必要があるのは、データを読み込み、処理し、モデルから予測結果を得るだけです。その後、感情分析のための事前学習済みモデルを使用し、洞察を得ることができます。

推論にはGoogle Colabを使用し(こちら)、結果をresult.csvにエクスポートしました。GitHubリポジトリのresultsに見つけることができます。その後、結果を別のGoogle Colabノートブックで分析し、対話型の体験を行いました。ですので、簡単かつインタラクティブに使用することもできます。

では、結果を確認しましょう!

与えられたスコアは非常にポジティブです。一般的に、ユーザーはこのアプリケーションを好きです。

これは感情分析とも一致しており、ほとんどのレビューはポジティブであり、ネガティブに分類されるレビューは最小限です。

上記から分かるように、モデルのパフォーマンスは理解しやすいです。ポジティブなスコアは他のスコアよりも圧倒的に高く、感情分析のグラフと同様です。

前に定義したカテゴリに関して、モデルはほとんどのレビューがユーザーの経験に関するものであると予測しています(他のカテゴリに関連する経験を除く):

以下に定義されたカテゴリごとの感情予測も表示できます:

レビューの詳細な分析は行いませんが、潜在的な問題の基本的な理解で十分です。したがって、最終データから簡単な結果をまとめるのに十分です:

  • サブスクリプションに関するレビューのほとんどがネガティブであることは理解できます。有料コンテンツは一般的にモバイルアプリケーションでは歓迎されません。
  • インターフェースに関するネガティブなレビューが多数あります。これはさらなる分析の手がかりとなるかもしれません。機能についての誤解があるか、ユーザーが考えていたように機能が機能しない可能性があります。
  • 記事は一般的に好まれ、ほとんどの人が良い経験をしました。

プロットに関する重要な注意事項:アプリケーションのバージョンでレビューをフィルタリングしていません。最新の現行バージョン(4.5)の結果を見ると、アプリケーションのインターフェースがユーザーを混乱させるか、迷惑なバグがあるようです。

結論

今、事前学習済みモデルを使用してモバイルアプリケーションの潜在的な問題点を理解し、特定の機能を分析することができます。

この例では、HuggingFaceの強力なAPIとAutoTrain、Kiliの使いやすいインターフェースを使用しました。AutoTrainを使用したモデリングにはわずか30分しかかかりませんでした。モデルの開発に自分自身で時間を費やしたため、AutoTrainは確かにはるかに効率的です。

コード、データセット、スクリプトはすべてGitHubで入手できます。AutoTrainモデルも試すことができます。

これは有効な出発点と考えられますが、より多くのデータを収集し、より良いパイプラインを構築する必要があります。より優れたパイプラインは、より効率的な改善につながります。

We will continue to update VoAGI; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

データサイエンス

「3つの質問:ロボットの認識とマッピングの研磨」

MIT LIDSのLuca CarloneさんとJonathan Howさんは、将来のロボットが環境をどのように知覚し、相互作用するかについて議論し...

データサイエンス

「David Smith、TheVentureCityの最高データオフィサー- インタビューシリーズ」

デビッド・スミス(別名「デビッド・データ」)は、TheVentureCityのチーフデータオフィサーであり、ソフトウェア駆動型のス...

人工知能

「リオール・ハキム、Hour Oneの共同創設者兼CTO - インタビューシリーズ」

「Hour Oneの共同創設者兼最高技術責任者であるリオール・ハキムは、専門的なビデオコミュニケーションのためのバーチャルヒ...

人工知能

「ナレ・ヴァンダニャン、Ntropyの共同創設者兼CEO- インタビューシリーズ」

Ntropyの共同創設者兼CEOであるナレ・ヴァンダニアンは、開発者が100ミリ秒未満で超人的な精度で金融取引を解析することを可...

人工知能

「15Rockの共同創業者兼CEO、ガウタム・バクシ氏によるインタビューシリーズ」

「ガウタム・バクシは、気候リスク管理とアドバイザリーサービスのグローバルリーダーである15Rockの共同創設者兼CEOですガウ...

人工知能

「コマンドバーの創設者兼CEO、ジェームズ・エバンスによるインタビューシリーズ」

ジェームズ・エバンズは、CommandBarの創設者兼CEOであり、製品、マーケティング、顧客チームを支援するために設計されたAIパ...