BERTを使って日本語タイトルからyoutuber予測してみた(2)
こんにちわんわん、まあるです。
情報系専攻の大学院に通う女子大学院生です🐶
今回は前回精度がうーんという感じだった日本語タイトルからyoutuberが誰なのかを予測するモデルの精度を上げてみようという記事です。
1回目はこちら↓
BERTを使って日本語タイトルからyoutuber予測してみた - 女子大生まあるの「好きに言わせてっ!」
2値分類にしているので、正解ラベル1には私の好きなyoutuberさん、不正解ラベル0には他のyoutuberさんのタイトルを用いています。
で、正解としたyoutuberさんのタイトルってすごく記号で強調や感情表現をするので、これは有効かも...!と思い、前処理の段階で削除しなかったんですね。
そしたら結果が良くなかった後、アノテーションスコアの上位を見てみると、どちらのラベルも記号が上位笑
よく考えたらyoutuberさんはタイトルで人目を惹きつけないといけないので派手に記号つけますよね、リサーチというか最初の分析不足でした^^;
なので記号を省きました

左のように記号で強調してた部分が消えて右側を見ると印象がだいぶ変わりますよね。
その後、モデル学習については1回目と同じような条件とし、変更なしで行いました。
結果は
'eval_accuracy': 0.7,
'eval_precision': 0.7083333333333333,
'eval_recall': 0.7,
'eval_f1': 0.696969696969697,
'eval_mcc': 0.408248290463863
ということで大体5%の増加となりました!!ヤッホイ♪
mccはもう少しデータを増やすか前処理で数字を消すなどすると50%台に乗りそうです。
混合行列の結果は

こうなりました。FP(偽陽性)が多めです。
前処理の重要性が今回でより実感できました。データサイエンスではこういった小さいミスでモデル選びミスることとかもあると考えると怖いですね。分析やアプローチの確立は大事だ〜〜〜😲
次はタイトルと高評価の相関とか、再生数が多いものと投稿曜日の関連とかもっと分析によった調査をしてみたいです。もしかしたら画像分類系にいってるかもですが、、、
以上で、少し精度上がったよ〜7割乗り上げた!の回でした。
ありがとうございました。
まある
BERTを使って日本語タイトルからyoutuber予測してみた
こんにちは。まあるです。
以前使ったことのあるBERTを用いてタイトルから私の好きなyoutuberさんを当てよう!という企画です。
BERTはGoogleが2018年に開発したNLPモデルです。
BERTとはで検索するとたくさん情報が見れるとおもいますので詳しいことは割愛します。
【注意】本実験では、公開されているYouTube動画タイトルを手動で収集・アノテーションし、個人利用・教育目的で機械学習に活用しました。
スクレイピングは使用しておらず契約違反にはならないはずですが、他の問題点ありましたらご指摘ください。削除いたします。
個人での開発のためデータは正解ラベル1(好きなyoutuberさんのタイトル)100件と不正解ラベル0(他のyoutuberさんのタイトル)100件の計200で作り、学習:評価 = 9:1としました。
データ作るのに20~30分、学習モデル作るのに30分、評価2分、環境構築に3日!!!!かかりました。なぜかtransformerのimportが4時間経っても進まないという状態に遭ってしまいlocalで実行するのを諦めてgoogle colabで実験しました、、、😭
環境構築何回やってもどっかでつまづくんだよね〜〜。 早くそこらへんも理解できるようになりたいものです。
好きなyoutuberさんとはLazy Lie Crazy【レイクレ】さんです!!
チャンネルはこちら↓大2からみてるんでもう4年目とかですね、ヤバ笑
少し話がそれましたが、
csvファイルには|index|title|label|という形で3列のデータが格納されています。
大まかな流れとしては
1.データ読み込み
2.データフレームに変換
3.データ前処理
私は小文字とneologdnを使った正規化のみしました。
4.BertJapaneseTokenizerを使ったトークン化
5.データローダ作成
6.学習
7.評価
---ここからは+α---
8.train lossとvalidation loss可視化
9.クラス別アテンションスコア化
こんな感じです。
評価の結果は以下になりました。
'eval_loss': 0.567703902721405,
'eval_accuracy': 0.65,
'eval_precision': 0.6648351648351649,
'eval_recall': 0.65,
'eval_f1': 0.6419437340153452,
'eval_mcc': 0.3144854510165755
微妙〜〜って感じですね。mccを見てもわかるように僅かに相関が見られるといった感じです。
accuracyもランダムより少し高いってくらいで使えるかというと使えないですね笑
混合行列で見てみます

他のyoutuberさんのタイトルでも正解ラベルとしてみられていますね。
原因をクラス別アテンションスコア化で見てみました。各クラス上位50件を表示し、助詞を外しています。


クラス1が正解のyoutuberさんタイトルです。データを収集しているときに【】をよく使うな、!もかなりあるなと思いあえて残したのですが他のyoutuberさんも当たり前に使うのでお互い上位にランクインしていて逆によくなかったのかもしれないです。
あとはwwwの笑いを表す単語も全体的に使われていて上位にありますね。
地獄とか過酷とか生活って単語は本当にレイクレはおなじみのタイトルなので上位に入っててしっかりアテンションできているなと感じました。
前処理の段階で記号を外したり数字も除外した方が精度が上がる気がします。
時間があれば精度が上がるかの検証をやってみようと思います。
以上、まあるでした!
なぜ経営者は孤独に苛まれる?しがない女子大学院生の考察
こんにちは、まあるです。
私は大学院に通いつつアルバイトに励む一般的な学生です。
いつかは会社を経営する社長になるぞ!と中学は本気で思っててより社会(社会人)に触れていくと現実はそんな甘いことないな〜と意欲が減ってってるのが本音です。
私の地域では私のことを純粋にすごいと思ってくれてる方々が多く、将来は雇ってね!とかどんな会社建てるの?とキラキラした目で言ってくれるので戦々恐々としてしまっています。今の私は、昔の野心に満ち溢れ何にでもなれると信じてた私とは大違いで、不安と欺瞞と恐怖で社会人になりたくないよー( ; ; )とイヤイヤ期きてます。他人と比べて自分に自信が持てていないんですよね、大海を知った蛙のようです。
そして最近よく考えてしまうのが今のアルバイト先の代表が立場を退くことを決めたのはなぜかということです。代表は地域貢献・学生のためにという目標を掲げ、それ通りに会社を運営していました。厳しいことをわたしたちに言うのにはそれ相応の思いがあると私は感じていました。しかしその厳しさが、ある学生にとっては代表に対する怖さや近寄り難いと言う気持ちに繋がっていたとも感じていました。
それを代表自身も感じていて、葛藤しているようにも見えました。
私自身も最初はイヤーな言い方された時にははい?って思いましたし、他の学生をみんなの前で怒る時はなんでわざわざみんなの前で?ってちょー思いました。でも、普段の姿はおっとりで面白いワクワクすることが好きな人と言う印象もありましたのでなんでか嫌いになれず、代表の葛藤するところを見た時は心が痛みました。私の態度もそう見えていたのかな、と。
経営者は孤高である。資金を得るためにはできない社員にケツを叩いて進めてもらわなきゃならないこともありますね。決定していかないといけないことばかりだし。負荷が高そうですよね。わたしたちだって期待に応えられるよう頑張るけどみんなが責任をまっとうできるかは分かりません。それ以外にも内容の齟齬があるのか、本当にやる気がなくて進められないのか、何が影響しているか経営者だけでは判断できないこともある。他者を率いる立場は常に皆をあらゆる攻撃から守る位置づけにいるように思われます。外からの攻撃だけでなく、それが中からもあるときは苦痛でしょう。
それに耐え得る人は共感性がないとか人に興味がない人ではないでしょうか。仲間意識だけでは下の者たちを引っ張れない。エゴが強く、生存バイアスも強くないといけないのではないでしょうか。でないと誰も守れないから。
でも他にも代表には訳があったのかな。体調面は心配なところあったし仕事ばかりしているようにも見えたけど。本人しかわからない部分ですかね。伝えようとはしないだろうな。
私は正直やめて欲しくないです。代表の先導があったおかげで仕事の仕方がわかったりやりがいが感じられたりした部分があったから。今も連絡とかメンション来ると怖いけど笑
経営者は孤独に戦う場面が多く、守っているはずのメンバーからも攻撃を受けやすいと思います。それでも、中には慕っていたり想いが通じていたりする人もいるということを忘れないでほしいなと思います。そしてその立場に立ったからこそわかる苦しさを知らない者にも伝える勇気を持ってほしいと思います。私たちなりに考えることはできるから。
以上しがない大学院生のまあるでした
バイチャ(^ ^)/
AtCoder ABC405 C問題解いてみた(Pythonだよ)
どうも、まあるです。
最近AtCoderを頑張っている後輩に触発されてABC問題当日には無理でしたが解いてみました。
pythonでしか解いたことない勢で、最適化とかアルゴリズムの知識皆無なのでいっつもCがTLEになるのですが今回は2回目に少し書き換えて見事ACできたのでまとめておこうと思います。
まず今回の問題がこちら↓。
簡単に説明すると、全てのペアの積の和を求めてねって問題ですね。
私が実装しようと思った考えが、サンプル問題で一個ずつ二つの数をかけて合計出してる説明を見た時に一つのかけられる数に対してかける数をまとめようという方法です。
例えば[3,5,6,2,1]とあったら最初のかけられる数を配列最初(0番目)の3として後ろ[3,5,6,2,1]部分を全て足して最後に3とかけちゃおうという作戦です。そして次はかけられる数をひとつずらした5としてその後ろ[3,5,6,2,1]をかける数と見てまとめて足して最後に5とかける。これを配列の最後から2番目まで続けて終了です。
式にすると{3*(5+6+2+1)}+{5*(6+2+1)}+{6*(2+1)}+(2*1)という計算方法です。
最初に書いたコードが以下になります。
from copy import copy
n = int(input())multiplied = list(map(int, input().split()))
multipty = copy(multiplied)
ans=0
for i in range(n-1):
multipty[i]=0
a_2 = sum(multipty)
a_1 = multiplied[0]*a_2
ans+=a_1
del multiplied[0]
print(ans)
見てわかるように無駄に配列二つ作ってますね笑
当初delを使うことにこだわってたのでfor文とのずれを解消するために二つ作ってました。かけられる数であるmultipliedの配列の0番目を指定して、かける数であるmultiplyの配列はかけられる数に使われる部分には0という値を再代入して、sum()で出すことでいらない数の合計を取得しないようにしました。
delは配列の最初を消して次のかけられる数が取得できるようにしているのですが、残念なことに一番目を消して全ての値を一個前に移動させることをするのでO(n)かかってしまうんですね〜〜
つまりfor文はひとつでもOが(n^2)かかっちゃう。これじゃあTLEだ。書いた直後は自信満々に出してて笑う笑
ということでじっと見てみると、あ、別に配列一つでいいぞと気づき、お、全ての値の合計値からかけられる数になる部分を毎回引いていけば一気に楽になるぞと書き換えられました。
n = int(input())
li = list(map(int, input().split()))
ans=0
total=sum(li)
for i in range(n-1):
total -= li[i]
ans+=li[i]*total
print(ans)
ということで俗にいう累積和の応用に近いのかなと思います。解説欄ではもっとすごい数学的最適化手法を使っていたのでそちらC++とかを使う人にはいいのかなと思います。
だとしても一発でTLEしないで行ける日は来るのか、、、センスとかもあるだろうな〜
ずっと思ってたけどAtCoder土曜日の夜9時ってお出かけ予定ある人には辛いよね。私毎週は参加できる気がしません(´・_・`)
時間変えてくれ〜〜と思うまあるでした。
まある
最長共通接頭辞(Longest Common Prefix)を自分で考えた実装でもLeetCodeで0msAcceptだった話
どうも、まあるです。ヤホ(๑>◡<๑)
今回はアルゴリズムが苦手すぎるので簡単な問題から理解していこうと思いLeetcodeのeasy問題から挑戦してみました。以下問題のリンクです。
こちらタイトルの通りLongest Common Prefix(=複数の言葉の全てで最初から一致する最長の部分)を求める問題になっています。
問題で与えられたのはlist型の1個だけです。
例えばlist = [july, jupyter, june]とあったら、全ての言葉で先頭から一致する部分を取り出すので答えは"ju"となります。
最長共通接頭辞という7字の漢字だけで理解できるようにした日本人、すごい超えてこわいですね😅
で、私ほんとに一般的な二分木とか再帰とかのアルゴリズムすらもまっっっっったく覚えられないので、当たり前のように思いつく実装で書きました。
class Solution(object):
def longestCommonPrefix(self, strs):
ans = ""
a = min(strs)
f = True
for s in range(len(a)):
check = ans+a[s]
for i in strs:
if not i.startswith(check):
f = False
if f:
ans+=a[s]
else:
break
return ans
これです。変数がわかりにくいaとかfだけの単語になっているのはお許しを、、、。
早くなる方法を考えた時に、基準にする単語をリストの中で一番短い言葉にしちゃえばいいのかなということでaを設定してます。fはflagの意味で基準にする言葉と違う文字が出てきたら即座に終了するために設けました。
二重ループなのですが2個目のfor文内でfalse受け取ったらすぐ終了できるよう1個目のfor文の最後にfがTrueかFalseかチェックしてFalseならbreakで終わらせてるという感じです。
エイヤー(><)とsubmitしたところこれが0msのところだったので驚きました!!

これがなぜ最長共通接頭辞を求める一般的なアルゴリズムと同じくらいの速さだったのか不思議がりました。
結論として
1.仮の接頭辞を決め一つでも異なればすぐに処理を終了している
2.startswith関数がC実装されていてpythonでも早い処理になっている
ことが理由かなと思います。
ですが1番の大きな理由はやはり、LeetCodeが入力サイズ制限しててあんま差が出ないから〜〜〜〜〜!あと極論文字を一つずつ見ていくしかないので計算量Oは変わらないってね笑
でも、自分の成長を感じられたし、少しずつ前に進む楽しさを知って何かにハマっていくことは全然あると思うので素直に喜んでEasy解き進めていけたらなと思います!
以上まあるでした!バイバイ👋😆
お久しぶりです。進学しました🌸
まあるです。
日々面白いこと起こってたのにこのブログ書かないとなと思いながらもう知らん間に一年たってました。ヤバ~(´・ω・`)
1年前に書いた記事読んでみたんですけど
S3でアップロードした画像ファイルを一致するか確かめてみた - 女子大生まあるの「好きに言わせてっ!」
↑これですね。なーんも覚えてなかった笑笑
人の記憶ってほんとに限りがありますね。てことでちゃんと意欲的に私という人間の思考の断片をデータの片隅に置いておこうと思います。
1年経つと人生の岐路に立ち、選択した後な訳で。
結論、まあるは女子大生から女子大学院生へと生まれ変わりました👏
私は周りの環境をすごく重要視するタイプなので色々考えて他大学院に進学することにしました。面白いことに環境や人々、生活スタイルすらも何もかもが変わり刺激的です。私は飽き性なので最高ですね。
人生を決めるのは私自身が行うことなのでどんな結果になったとしても後悔はしてこなかった人間です。このまま、最悪な環境や目指す未来と違う状況になったとしてもやりたいことはつきませんので楽しんでいきたいと思います〜!
今年度の目標は、技術系の内容を増やす。資格を取る。韓国で美容サロンor美容外科に行く。です。
よろしくお願いしまーす^ ^
まある
S3でアップロードした画像ファイルを一致するか確かめてみた
まあるです。
本日AWSのS3にあげた画像が容量は一緒だが中身の画像が違う場合にどうやったらその差異を見つけられるかなと調べていたら出てきた「ETag」について書き留めたいと思います。
結論から言うとこれでは私の画像の差異を見つけられず没になりました笑
でもせっかく調べていつか使うかもだし、、、記事に残す次第です!
最初はOpenCVでの画素を調べて2点の差分をとる方法が出てきましたが、なんというかこれでは求めていることに対してのコード書く時間や負担が大きすぎるなと思い、違うアプローチを探しました。
次にAWSにばっちし書いてた「ETag」ですね
詳しくはこちら
ファイルの整合性を確かめてくれるものらしいです。
読み方はエンティティタグ。
実物を示すタグみたいな意味なのかな?わかる人教えてください笑
実装としてpython boto3で組みました。
S3からETagを取得する際は
オブジェクトを初期化してS3のクライアントを作成したあとにhead_object()しました
S3のクライアントをs3_clientとすると
result = s3_client.head_object(Bucket=bucket_name, Key=path/test.csv)
result['ETag']
bucket_nameにはファイルが入っているS3のバケット名、pathにはバケットからそのファイルまでの道を書きます。
2行目をprintすると文字列の羅列が出てきます。
次にローカルの画像からETagを取得する際は
hashlibモジュールを使用してMD5ハッシュ値を調べました。
import hashlib
with open(file_path, "rb") as f:
for chunk in iter(lambda: f.read(4096), b""):
hash_md5.update(chunk)
return hash_md5.hexdigest()
上記を関数としてfile_pathにファイルの保存先を記入します。
printするとMD5の結果が出てきます。
今回試した画像では作られた日付も出力した内容も違かったんですが同じ値が出てきていました。それはそれで調査ミスかもしれないです。思い当たる節がある、、、😭
今回はS3内のETagの出力方法やhashlibの使い方がわかって勉強になりました。
まある
参考:
EtagをつかってS3にアップロードしたファイルの整合性をたしかめてみる(マルチパートアップロードなし) #AWS - Qiita