datasets経由でoscar-corpus/OSCAR-2301をダウンロードする

初めに

テキストのコーパスとして以下のoscar-corpus/OSCAR-2301があります。こちらをダウンロードするコードのメモになります

huggingface.co

開発環境

ライブラリのインストール

!pip install datasets
!pip install zstandard

データセットのダウンロード

ja(日本語)のデータだけダウンロードします

from datasets import load_dataset

# ja(日本語)のデータセットをダウンロード
dataset = load_dataset("oscar-corpus/OSCAR-2301", "ja", split="train")

# データセットの情報を表示
print(dataset)

bertモデルを使ってlivedoorニュースの分類をする

初めに

色々LLMを触ってきて、ちゃんと?bertを触ったことがないので以下の記事を自分でもやってみます.
一部記事の内容から変更して実行しています

soroban.highreso.jp

以下でColobは公開しています

colab.research.google.com

また作成したモデルは以下で公開しています

huggingface.co

環境

準備

ライブラリのインストール

!pip install transformers==4.28.0
!pip install nlp
!pip install datasets
!pip install fugashi
!pip install ipadic
!pip install sentencepiece
!pip install scikit-learn
!pip install tensorboard

データの取得と整理

!wget "https://www.rondhuit.com/download/ldcc-20140209.tar.gz"

# ファイルを解凍し、カテゴリー数と内容を確認
import tarfile
import os
# 解凍
tar = tarfile.open("ldcc-20140209.tar.gz", "r:gz")
tar.extractall("./data/livedoor/")
tar.close()
# ディレクトリのファイルとディレクトリを確認
files_folders = [name for name in os.listdir("./data/livedoor/text/")]
print(files_folders)
# カテゴリーのディレクトリのみを抽出
categories = [name for name in os.listdir(
    "./data/livedoor/text/") if os.path.isdir("./data/livedoor/text/"+name)]
print("カテゴリー数:", len(categories))
print(categories)

import glob  # ファイルの取得に使用
import os
path = "./data/livedoor/text/"  # ディレクトリの場所を指定
dir_files = os.listdir(path=path)#指定したpathのファイルとディレクトリの一覧を取得
dirs = [f for f in dir_files if os.path.isdir(os.path.join(path, f))]  # ディレクトリをリストとして取り出す
text_label_data = []  # 文章とラベルのセット
dir_count = 0  # ディレクトリ数のカウント
file_count= 0  # ファイル数のカウント
for i in range(len(dirs)):#ディレクトリの数だけループ処理
    dir = dirs[i]#ディレクトリの名前を取り出す
    files = glob.glob(path + dir + "/*.txt")  # ファイルの一覧
    dir_count += 1
    for file in files:
        if os.path.basename(file) == "LICENSE.txt":#LICENSE.txtは除外する(ループをスキップ)
            continue
        with open(file, "r") as f:#ファイルを開く
            text = f.readlines()[3:]#指定の行だけ読み込む 4行目以降を読み込む
            text = "".join(text)#リストなのでjoinで結合する 空の文字列に結合して一つの文字列にする
            text = text.translate(str.maketrans({"\n":"", "\t":"", "\r":"", "\u3000":""})) #不要な文字を除去する
            text_label_data.append([text, i])#本文とディレクトリ番号をリストに加える
        file_count += 1
        print("\rfiles: " + str(file_count) +" "+ "dirs: " + str(dir_count), end="")

import csv
from sklearn.model_selection import train_test_split
news_train, news_test =  train_test_split(text_label_data, shuffle=True)  # 学習用とテスト用に分割
news_path = "./data/"
with open(news_path+"news_train.csv", "w") as f:#学習データ
    writer = csv.writer(f)#writerを作る
    writer.writerows(news_train)#csvファイルとして書き込み
with open(news_path+"news_test.csv", "w") as f:#テストデータ
    writer = csv.writer(f)
    writer.writerows(news_test)

モデルの学習

from transformers import BertForSequenceClassification, BertJapaneseTokenizer
sc_model = BertForSequenceClassification.from_pretrained("cl-tohoku/bert-base-japanese-whole-word-masking", num_labels=9)#事前学習済みBERTモデルの読み込み
sc_model.cuda()#GPU対応
tokenizer = BertJapaneseTokenizer.from_pretrained("cl-tohoku/bert-base-japanese-whole-word-masking")#事前学習済みのBERTトークナイザーを読み込み

from datasets import load_dataset
def tokenize(batch):
    return tokenizer(batch["text"], padding=True, truncation=True, max_length=512) #受け取ったバッチからtextデータを取り出してtokenizerに入れる
news_path = "./data/"
train_data = load_dataset("csv", data_files=news_path+"news_train.csv",column_names=["text", "label"], split="train")#CSVデータの読み込み #カラムの指定,#学習データとテストデータは事前に分割済みのためtrainを指定
train_data = train_data.map(tokenize, batched=True,batch_size=len(train_data))#単語ごとに分割する  #バッチサイズは学習データすべてを指定
train_data.set_format("torch", columns=["input_ids", "label"])#学習データのフォーマット指定,Pytorchを指定,input_idsとlabelのカラムを指定
test_data = load_dataset("csv", data_files=news_path+"news_test.csv", column_names=["text", "label"], split="train")#学習データとテストデータは事前に分割済みのためtrainを指定
test_data = test_data.map(tokenize, batched=True, batch_size=len(test_data))
test_data.set_format("torch", columns=["input_ids", "label"])

from sklearn.metrics import accuracy_score
def compute_metrics(result):
    labels = result.label_ids
    preds = result.predictions.argmax(-1)
    acc = accuracy_score(labels, preds)
    return {
        "accuracy": acc,
    }

from transformers import Trainer, TrainingArguments
training_args = TrainingArguments(
    output_dir = "./data/results",
    num_train_epochs = 2,
    per_device_train_batch_size = 16,
    per_device_eval_batch_size = 32,
    warmup_steps = 500,  # 学習係数が0からこのステップ数で上昇
    weight_decay = 0.01,  # 重みの減衰率
    logging_dir = "./data/logs",
    evaluation_strategy = "steps"
)
trainer = Trainer(
    model = sc_model,
    args = training_args,
    compute_metrics = compute_metrics,
    train_dataset = train_data,
    eval_dataset = test_data,
)

trainer.train()

モデルの評価

trainer.evaluate()

lossは以下のようになっています

モデルの保存とhuggingfaceへのアップロード

以下でモデルをローカルに保存します

news_path = "./data/"
sc_model.save_pretrained(news_path)
tokenizer.save_pretrained(news_path)

以下で /data ディレクトリの中をhuggingfaceにアップロードします

!huggingface-cli upload ayousanz/bert-livedoor-news-category data .

追加学習をしたモデルを使って分類

import glob  # ファイルの取得に使用
import os
import torch
import random
category_list = ["dokujo-tsushin", "it-life-hack", "livedoor-homme","kaden-channel", "movie-enter", "sports-watch","smax","topic-news","peachy"]
category = random.choice(category_list)
#print("dirname:", category)
random_number = random.randrange(1, 99)
#print(random_number)
sample_path = "./data/livedoor/text/"  # ディレクトリの場所を指定
files = glob.glob(sample_path + category + "/*.txt")  # ファイルの一覧
file = files[random_number]  # 適当なニュースを1つ取り出した
file_name = os.path.basename(file)
#print("filename:", file_name)
dir_files = os.listdir(path=sample_path)
dirs = [f for f in dir_files if os.path.isdir(os.path.join(sample_path, f))]  # ディレクトリ一覧
with open(file, "r") as f:
    sample_text = f.readlines()[3:]
    sample_text = "".join(sample_text)
    sample_text = sample_text.translate(str.maketrans({"\n":"", "\t":"", "\r":"", "\u3000":""})) 
print(sample_text)
max_length = 512
words = loaded_tokenizer.tokenize(sample_text) #torknizeを行う
word_ids = loaded_tokenizer.convert_tokens_to_ids(words)  # 単語をインデックスに変換
word_tensor = torch.tensor([word_ids[:max_length]])  # テンソルに変換 スライスを使って単語が512より多い場合は切る
x = word_tensor.cuda()  # GPU対応
y = loaded_model(x)  # 予測
pred = y[0].argmax(-1)  # 最大値のインデックス
print("predict-result:", dirs[pred])

こちらを実行すると以下のように分類してくれます

オンラインゲーム(いわゆるネトゲ)は、インターネットに繋がっているため様々な問題が発生する。不正対象となるオンラインゲーム上での経済活動として話題になるのがRMTだ。RMTは「リアルマネートレード」の略で、ゲーム内の通貨やアイテムなどを、実際のお金でユーザー同士が売買するというものだ。長時間かけないと取れないレアアイテムなどは、数千〜数万円で取り引きされ、レアアイテムだけを狙う輩がPOP場所にずっと張り付き占有してしまうことでゲームバランスが大きく崩れてしまう原因にもなっている。このような悪質な行為はゲームの規約などで禁止されていることが多い。先日発売されたWii用ゲームのドラクエXでも当然禁止されているが、悲しいかなRMTでアイテムやゲーム内の通貨をやりとりしようとしている人もいるようだ。オンラインゲーム内にはアイテム交換などができる仕組みがある。これはゲーム内で仲良くなったキャラクター同士のアイテム交換などが本来の目的だ。この仕組みを利用して、ゲーム外で実際のお金をやりとりし、アイテムやゲーム内の通貨売買を行うのがRMTだ。RMTはドラクエXのような同時に大人数が遊ぶMMORPG以外でも、主にスマートフォンなどで遊ぶソーシャルゲームと言われる物でも問題になっている。ゲームにアイテム交換などの仕組みがある限り、ゲーム外での金銭の授受を技術的に防ぐことは難しい。■それなりに稼げるゲームの規約などともかく、RMTをよく思わないユーザーも少なくないが、規約違反であろうが手っ取り早くゲームを攻略できるようになるならRMTを使うのもよしとするユーザーもいる。悪いことをしても、ばれなきゃOKという間違った考えに基づいているわけだ。例えば、ドラクエXではゲーム内の通貨「ゴールド」を貯めるのに時間がかかる。今までのドラクエシリーズのようにモンスターを倒して集めていては時間がかかりすぎるが、ゲーム内で職人となり武器や道具などを生産してゲーム内で販売することで、ゴールドもそれなりに貯まるようになっている。この仕組みをよく知らなかったり、面倒だと思うと、ネット上でRMT業者がゴールドを売ってたら買いたくなる人もいるだろう。ある程度、この仕組みなどをフル活用してゴールドを効率的に稼げるようになったら、業者にゴールドを買い取ってもらいたい人もいるかもしれない。例えば、1時間で2000ゴールド増やせるとして、それを1000円で販売できれば、普通にアルバイトなどをするのと同じくらい稼げることになる。個人が、アルバイト感覚でやるなら規模も小さいが、業者がプログラムを操作して、自動的にそのようなことを行う場合もある。これをBOTなどというが、Wii用のドラクエXの場合、ゲーム専用機ということで難しいが、PC用のゲームでは実際にプログラムを操作したり、マクロを組んだりして手動だと割に合わないことを複数のアカウントを使い大規模に行っていることもある。当然ながら、このような行為が運営側に発覚した場合、アカウント剥奪などの処分を受けることになる。RMT行為はほとんどのオンラインゲームでも原則禁止されている行為である。この問題はどのオンラインゲームにも共通して存在しているが、ユーザーが多ければ多いほど多くの問題が発生する可能性がある。世界中から接続可能なオンラインゲームの場合、日本人向けのサーバーにRMT目的の外国人が大量に接続して乱獲しまくることで通常のプレイに支障が出ることがある。特に中華圏からの接続が多いみたいだ。彼らにとっての数万円は日本人にとっての数十万円に匹敵する価値があるので、それこそ死に物狂いで狩りを行う。生活がかかっているから何でもアリ、お構いなしだ。BANされるまでひたすら周囲に迷惑をかけまくり、BANされたら新アカウントを作ってまたやってくる。これを防ぐには、運営側の対処も重要だが、ユーザー同士がこうした行為をしないようにするのも重要だ。しかし、ドラクエXのようにオンラインゲームに慣れていないユーザーが多い場合はこれもまた難しい。結局はプレイヤーの良心に訴えるしかないというのが現状だ。こうしたRMT行為はいたちごっこで今後も続いて行くのだろう。上倉賢 @kamikura [digi2(デジ通)] digi2は「デジタル通」の略です。現在のデジタル機器は使いこなしが難しくなっています。皆さんがデジタル機器の「通」に近づくための情報を、皆さんよりすこし通な執筆陣が提供します。■デジ通の記事をもっと見る・iPhone 4Sの音声認識機能は使える 新しいiPadでも使える音声認識・英語の音声認識で英会話練習 自分の発音を客観的に知る方法・サービス終了後はどうなる!電子書籍は永遠に読めるのか・キンドルが日本に参入する?Amazonの電子書籍をおさらい・iPhoneが据え置きゲーム機も殺す?多機能化するスマートフォンドラゴンクエストX 目覚めし五つの種族 オンライン (Wii USBメモリー16GB同梱版) (封入特典:ゲーム内アイテムのモーモンのぼうし同梱)クチコミを見る
predict-result: it-life-hack

LinuxでnvitopでGPU・CPU・メモリの監視をする

初めに

CLI上でメモリやGPUの使用量を監視するためのコマンドは以下のようなものがあります

  • top(CPUとメモリ)
  • htop(CPUとメモリ)

  • nvidia-smi(GPUがメイン)

github.com

公式のReadMeを見ると以下のように見えるとのことです

開発環境

詳細

以下でインストールをします

pip3 install --upgrade nvitop

以下で簡易的にGPUの使用量を見れます

nvitop -1 -c

huggingfaceのCacheパスを変更する

開発環境

詳細

以下を参考に参照するパスを変更します。ターミナルを立ち上げるごとに設定する必要があります

huggingface.co

$env:HF_DATASETS_CACHE = "full path"

日本語を含むZipファイルをコマンドから解凍する

初めに

zipファイルを解凍するコマンドでは、日本語を含むzipファイルの場合文字化けをします。そこで違うコマンドを使用します

開発環境

詳細

インストール

brew install unar

一つのファイルを解凍

unar 'ファイル名.zip'

フォルダ内すべてを解凍

find . -name "*.zip" -exec unar -o . {} \;

ESPNet2を使った音声とテキストのアライメント処理

開発環境

ライブラリのインストール

以下で必要なライブラリを入れます

pip install soundfile espnet_model_zoo torch
sudo pip install soundfile espnet_model_zoo torch

アライメント処理

以下を参考にコードを書いていきます。

github.com

モデルは reazon-research/reazonspeech-espnet-v2を使用します

espnet_model_zooを使用する場合は、以下から任意のモデルを指定してください

github.com

import soundfile
from espnet_model_zoo.downloader import ModelDownloader
from espnet2.bin.asr_align import CTCSegmentation
d = ModelDownloader(cachedir="./modelcache")
# esp model zooの場合
# model = d.download_and_unpack("Shinji Watanabe/laborotv_asr_train_asr_conformer2_latest33_raw_char_sp_valid.acc.ave")

# hfの場合
model = d.download_and_unpack("reazon-research/reazonspeech-espnet-v2")
speech, rate = soundfile.read("VOICEACTRESS100_001.wav")

duration = len(speech) / rate

print(f"音声ファイルの長さ: {duration:.2f}秒")

aligner = CTCSegmentation(**model, kaldi_style_text=False)

text = ["また、東寺のように、五大明王と呼ばれる、主要な明王の中央に配されることも多い。"]

segments = aligner(speech, text)

print(segments)

実行結果は以下です

音声ファイルの長さ: 6.91秒
WARNING:root:No RNN model detected; memory consumption may be high.
utt_0000 utt 0.02 41.39 -4.9689 また、東寺のように、五大明王と呼ばれる、主要な明王の中央に配されることも多い。

音声の長さを正確には取れていないですが、アライメントの精度は取得できそうです

KenLMで日本語文章の品質の評価

初めに

以下でLLMを使って文章の評価をしていますが、速度が速いと言われるKenLMでも評価してみます

ayousanz.hatenadiary.jp

開発環境

  • Ubuntu22.02

環境構築

sudo apt install build-essential cmake libboost-system-dev libboost-thread-dev libboost-program-options-dev libboost-test-dev libeigen3-dev zlib1g-dev libbz2-dev liblzma-dev
pip install https://github.com/kpu/kenlm/archive/master.zip
mkdir -p data/lm_sp
wget -c  -P data/lm_sp http://dl.fbaipublicfiles.com/cc_net/lm/ja.arpa.bin
wget -c  -P data/lm_sp http://dl.fbaipublicfiles.com/cc_net/lm/ja.sp.model

評価コード

import sys
import json
import csv
import kenlm

if __name__ == '__main__':
    with open("testData.txt", "r", encoding="utf-8") as f:
        lines = [line.strip() for line in f.readlines()[:30]]

    m = kenlm.LanguageModel("data/lm_sp/ja.arpa.bin")
    results = []

    for inp in lines:
        sentence = " ".join(inp)
        ppl = m.perplexity(sentence)
        results.append({"text": inp, "perplexity": ppl})
        print(ppl, inp)

    # Save results to JSON
    with open("kenlm_results.json", "w", encoding="utf-8") as f:
        json.dump(results, f, ensure_ascii=False, indent=4)

    # Save results to CSV
    with open("kenlm_results.csv", "w", newline="", encoding="utf-8") as f:
        fieldnames = ["text", "perplexity"]
        writer = csv.DictWriter(f, fieldnames=fieldnames)
        writer.writeheader()
        writer.writerows(results)

結果

text perplexity
それと僕が材料をお伝えした時にバニラエッセンスを入れたじゃないですか 17708.545685079465
1弦の5フレット、2弦の5フレット、 3弦の5フレット、2弦の7フレット、 38831.77205605622
けどもこれでえっと木スキル使うとさらに カウンターが1個貯まる 24178.439407054473
長い年月をかけて韓国人朝鮮人 と向き合ってきた中国人は韓国人 4482.124515163107
ごいハマり始めて 48969.93621135036
50話 いらっしゃいませ♪ ヘラのグランプリ! 93303.59762963047
オムニテクでは人々を助けを上がっている。 11689.811696733246
ステーキってもんはね 11286.760319052344
これが聞こえてきた 32392.71212184362
なるほどねそうなんだやばいすげ えわ 61553.26800664746
殺菌得ながらを 29143.353748316073
じゃあ呼吸法やりましょう、呼吸、呼吸 38638.26899312117
カンタ : そこやれるの見たいと思ってるよ、みんな 9503.800827281371
すげーなんか色んなものがこう そうなんだそうそうばすごいね 25696.966294762613
前回は standard assets を使って 遊んでいました 11098.166969108926
を獲得しました 9788.759603258804
しかしながら本当の理由はそれ だけではないのです 19715.238260370395
病むなんですが 59993.44877269272
全体混ぜると これね混ぜたら数分蒸らした方がいいです 38897.14236642167
アプリはそういったことを解決して くれるアプリです 15731.816412536211
ご丁寧に 106622.48885797341
下に 20732.22627445443
合わせてかぶせれば... 4003.3841234749957
そういう言い方で 32015.60911488846
朝食 69290.91681309085
流行ったものだそうですが 59954.375082911676
こうなります 9752.564887711484
次は釣りレベルの上限解放です。今度は何を釣らされるんだろうと思っていましたが、タマカイでした。 13016.617360872806
守りたい 17245.44873923792
だってさっきの人从众… 107673.84311097601

sentencepieceを使った場合

以下のコードを実行します

import sys
import kenlm
import sentencepiece
import unicodedata


if __name__ == '__main__':
    if len(sys.argv) < 3:
        print("Need ken_lm.arpa sentencepiece.model")
        sys.exit(-1)

    m = kenlm.LanguageModel(sys.argv[1])

    sp = sentencepiece.SentencePieceProcessor()
    sp.load(sys.argv[2])


    inputs = [
    '東京の夜景は美しい',
    '東京はいつも賑やかだ',
    '東京の街並みは独特だ',
    '東京の交通網は発達している',
    '東京は日本の経済の中心地だ',
    '東京の人口密度は高い',
    '東京の物価は高い',
    '東京の食文化は豊か',
    '東京のファッションは先進的',
    '東京の技術力は世界的だ',
    '東京の大学は有名だ',
    '東京の歴史は古い',
    '東京の伝統文化は守られている',
    '東京のサブカルチャーは多様だ',
    '東京のイベントは年中開催されている',
    '東京の公園は憩いの場だ',
    '東京の建築物はモダンだ',
    '東京の治安は良い',
    '東京の医療水準は高い',
    '東京の教育レベルは高い',
    '東京の環境対策は進んでいる',
    '東京の国際化は進んでいる',
    '東京のスポーツ施設は充実している',
    '東京の芸術活動は盛んだ',
    '東京の観光地は人気がある',
    '東京の祭りは活気がある',
    '東京の若者文化は独特だ',
    '東京の高齢化対策は課題だ',
    '東京の防災意識は高い',
    '東京の未来は明るい'
]

    for inp in inputs:
        # pretrained model in cc_net uses 'NFD' normalization?
        # TODO: Use https://github.com/facebookresearch/cc_net/blob/main/cc_net/text_normalizer.py
        text = unicodedata.normalize('NFD', inp)

        toks = sp.encode(text, out_type=str)
        print(toks)

        sentence = " ".join(toks)
        ppl = m.perplexity(sentence)
        print(ppl, inp)

実行コマンド

python sentencepiece2.py data/lm_sp/ja.arpa.bin data/lm_sp/ja.sp.model

結果

['▁東京', '', '', '晴れ', '']
4335.906162754335 東京はッ晴れ。
['▁東京', '', '元気', '', '', '']
4789.530541202564 東京は元気です。
['', '', '', '', '', '', 'ある', '.', '', '名前は', '', '', 'ない', '.']
677.481230499526 吾輩は猫である. 名前はまだない.
['▁東京', '', '晴れ', '']
1411.807566253476 東京は晴れ。
(venv) jovyan@yousan-0:~/lingua$ python sentencepiece1.py data/lm_sp/ja.arpa.bin data/lm_sp/ja.sp.model
['▁東京', '', '', '晴れ', '']
4335.906162754335 東京はッ晴れ。
['▁東京', '', '元気', '', '', '']
4789.530541202564 東京は元気です。
['', '', '', '', '', '', 'ある', '.', '', '名前は', '', '', 'ない', '.']
677.481230499526 吾輩は猫である. 名前はまだない.
['▁東京', '', '晴れ', '']
1411.807566253476 東京は晴れ。
(venv) jovyan@yousan-0:~/lingua$ python sentencepiece2.py data/lm_sp/ja.arpa.bin data/lm_sp/ja.sp.model
['▁東京', '', '夜景', '', '美しい']
1559.0554329452627 東京の夜景は美しい
['▁東京', '', 'いつも', '', '', '', '']
3771.668858772643 東京はいつも賑やかだ
['▁東京', '', '街並み', '', '', '', '']
2254.075478011484 東京の街並みは独特だ
['▁東京', '', '交通', '', '', '発達', 'している']
462.1914030627983 東京の交通網は発達している
['▁東京', 'は日本の', '経済', 'の中心地', '']
12523.705943574623 東京は日本の経済の中心地だ
['▁東京', '', '人口密度は', '高い']
1873.5702551396657 東京の人口密度は高い
['▁東京', '', '物価', '', '高い']
2306.9409256720432 東京の物価は高い
['▁東京', '', '食文化', '', '', '']
884.7496414993681 東京の食文化は豊か
['▁東京', '', 'ファッション', '', '先進', '']
942.4886609919694 東京のファッションは先進的
['▁東京', 'の技術', '', '', '世界的', '']
6352.528697589843 東京の技術力は世界的だ
['▁東京', '', '大学', '', '有名', '']
4518.518393639697 東京の大学は有名だ
['▁東京', 'の歴史', '', '古い']
1017.684104811051 東京の歴史は古い
['▁東京', '', '伝統文化', '', '', 'られている']
1318.7390808197645 東京の伝統文化は守られている
['▁東京', '', '', '', 'カルチャー', '', '多様', '']
16807.129140261182 東京のサブカルチャーは多様だ
['▁東京', '', '', '', 'ント', '', '', '', '開催されている']
5225.4904688694405 東京のイベントは年中開催されている
['▁東京', '', '公園', '', '憩いの場', '']
8311.233290969833 東京の公園は憩いの場だ
['▁東京', '', '建築物', '', '', '', '', '']
10915.668390212073 東京の建築物はモダンだ
['▁東京', '', '治安', '', '良い']
1337.6293205006057 東京の治安は良い
['▁東京', '', '医療', '水準', '', '高い']
859.5305593891276 東京の医療水準は高い
['▁東京', 'の教育', '', '', '', '', '高い']
11565.088896342308 東京の教育レベルは高い
['▁東京', '', '環境', '対策', '', '', '', '', 'いる']
5312.109623816024 東京の環境対策は進んでいる
['▁東京', 'の国際', '', '', '', '', '', 'いる']
8152.9475124097125 東京の国際化は進んでいる
['▁東京', '', '', '', 'ーツ', '施設は', '充実', 'している']
9341.116680821911 東京のスポーツ施設は充実している
['▁東京', '', '芸術', '活動', '', '盛ん', '']
1878.5996129207565 東京の芸術活動は盛んだ
['▁東京', '', '観光地', '', '人気', '', 'ある']
7621.730945021132 東京の観光地は人気がある
['▁東京', '', '祭り', '', '', '', '', 'ある']
2674.160008880571 東京の祭りは活気がある
['▁東京', '', '若者', '文化', '', '', '', '']
1578.6075972487467 東京の若者文化は独特だ
['▁東京', '', '高齢化', '対策', '', '課題', '']
4875.003477257479 東京の高齢化対策は課題だ
['▁東京', '', '防災', '意識', '', '高い']
1151.5175930579533 東京の防災意識は高い
['▁東京', '', '未来', '', '明るい']
1190.656783416366 東京の未来は明るい

参考サイト

zenn.dev