【入門】BERTによる日本語文書分類

本記事では、ニュース記事をカテゴリに分類するタスクを通して、事前学習済みBERTモデルをファインチューニングする方法を解説していきます。 入力データを変えるだけで任意の日本語文書分類タスクに応用可能です。

英語を対象とした文書分類のチュートリアルは、以下の記事をご覧ください。

環境設定

コードの実行はGoogle Colaboratoryで行います。記事内で紹介したコードをすべて含むノートブックは、以下のリンクから直接参照することができます。

Open In Colab

BERTによる日本語文書分類

公開データであるlivedoorニュースコーパスを用います。 このデータは、各ニュース記事に9種類のジャンルカテゴリのうちのいずれかが振られています。このカテゴリに分類するタスクを対象に、BERTによる文書分類モデルを実装していきます。

データの読込

まずは対象のデータをダウンロードして整形します。

# livedoorニュースコーパスのダウンロード
!wget https://www.rondhuit.com/download/ldcc-20140209.tar.gz
!tar zxvf ldcc-20140209.tar.gz

# 整形結果格納用ファイル作成
!echo -e "filename\tarticle"$(for category in $(basename -a `find ./text -type d` | grep -v text | sort); do echo -n "\t"; echo -n $category; done) > ./text/livedoor.tsv

# カテゴリごとに格納
!for filename in `basename -a ./text/dokujo-tsushin/dokujo-tsushin-*`; do echo -n "$filename"; echo -ne "\t"; echo -n `sed -e '1,3d' ./text/dokujo-tsushin/$filename`; echo -e "\t1\t0\t0\t0\t0\t0\t0\t0\t0"; done >> ./text/livedoor.tsv
!for filename in `basename -a ./text/it-life-hack/it-life-hack-*`; do echo -n "$filename"; echo -ne "\t"; echo -n `sed -e '1,3d' ./text/it-life-hack/$filename`; echo -e "\t0\t1\t0\t0\t0\t0\t0\t0\t0"; done >> ./text/livedoor.tsv
!for filename in `basename -a ./text/kaden-channel/kaden-channel-*`; do echo -n "$filename"; echo -ne "\t"; echo -n `sed -e '1,3d' ./text/kaden-channel/$filename`; echo -e "\t0\t0\t1\t0\t0\t0\t0\t0\t0"; done >> ./text/livedoor.tsv
!for filename in `basename -a ./text/livedoor-homme/livedoor-homme-*`; do echo -n "$filename"; echo -ne "\t"; echo -n `sed -e '1,3d' ./text/livedoor-homme/$filename`; echo -e "\t0\t0\t0\t1\t0\t0\t0\t0\t0"; done >> ./text/livedoor.tsv
!for filename in `basename -a ./text/movie-enter/movie-enter-*`; do echo -n "$filename"; echo -ne "\t"; echo -n `sed -e '1,3d' ./text/movie-enter/$filename`; echo -e "\t0\t0\t0\t0\t1\t0\t0\t0\t0"; done >> ./text/livedoor.tsv
!for filename in `basename -a ./text/peachy/peachy-*`; do echo -n "$filename"; echo -ne "\t"; echo -n `sed -e '1,3d' ./text/peachy/$filename`; echo -e "\t0\t0\t0\t0\t0\t1\t0\t0\t0"; done >> ./text/livedoor.tsv
!for filename in `basename -a ./text/smax/smax-*`; do echo -n "$filename"; echo -ne "\t"; echo -n `sed -e '1,3d' ./text/smax/$filename`; echo -e "\t0\t0\t0\t0\t0\t0\t1\t0\t0"; done >> ./text/livedoor.tsv
!for filename in `basename -a ./text/sports-watch/sports-watch-*`; do echo -n "$filename"; echo -ne "\t"; echo -n `sed -e '1,3d' ./text/sports-watch/$filename`; echo -e "\t0\t0\t0\t0\t0\t0\t0\t1\t0"; done >> ./text/livedoor.tsv
!for filename in `basename -a ./text/topic-news/topic-news-*`; do echo -n "$filename"; echo -ne "\t"; echo -n `sed -e '1,3d' ./text/topic-news/$filename`; echo -e "\t0\t0\t0\t0\t0\t0\t0\t0\t1"; done >> ./text/livedoor.tsv

# 確認
!head -10 ./text/livedoor.tsv
--- 出力 ---
filename    article dokujo-tsushin  it-life-hack    kaden-channel   livedoor-homme  movie-enter peachy  smax    sports-watch    topic-news
dokujo-tsushin-4778030.txt   もうすぐジューン・ブライドと呼ばれる6月。独女の中には自分の式はまだなのに呼ばれてばかり……という「お祝い貧乏」状態の人も多いのではないだろうか? さらに出席回数を重ねていくと、こんなお願いごとをされることも少なくない。  「お願いがあるんだけど……友人代表のスピーチ、やってくれないかな?」  さてそんなとき、独女はどう対応したらいいか?  最近だとインターネット等で検索すれば友人代表スピーチ用の例文サイトがたくさん出てくるので、それらを参考にすれば、無難なものは誰でも作成できる。しかし由利さん(33歳)はネットを参考にして作成したものの「これで本当にいいのか不安でした。一人暮らしなので聞かせて感想をいってくれる人もいないし、かといって他の友人にわざわざ聞かせるのもどうかと思うし……」ということで活用したのが、なんとインターネットの悩み相談サイトに。そこに作成したスピーチ文を掲載し「これで大丈夫か添削してください」とメッセージを送ったというのである。  「一晩で3人位の人が添削してくれましたよ。ちなみに自分以外にもそういう人はたくさんいて、その相談サイトには同じように添削をお願いする投稿がいっぱいありました」(由利さん)。ためしに教えてもらったそのサイトをみてみると、確かに「結婚式のスピーチの添削お願いします」という投稿が1000件を超えるくらいあった。めでたい結婚式の影でこんなネットコミュニティがあったとは知らなかった。  しかし「事前にお願いされるスピーチなら準備ができるしまだいいですよ。一番嫌なのは何といってもサプライズスピーチ!」と語るのは昨年だけで10万以上お祝いにかかったというお祝い貧乏独女の薫さん(35歳)  「私は基本的に人前で話すのが苦手なんですよ。だからいきなり指名されるとしどろもどろになって何もいえなくなる。そうすると自己嫌悪に陥って終わった後でもまったく楽しめなくなりますね」    サプライズスピーチのメリットとしては、準備していない状態なので、フランクな本音をしゃべってもらえるという楽しさがあるようだ。しかしそれも上手に対応できる人ならいいが、苦手な人の場合だと「フランク」ではなく「しどろもどろ」になる危険性大。ちなみにプロの司会者の場合、本当のサプライズではなく式の最中に「のちほどサプライズスピーチとしてご指名させていただきます」という一言があることも多いようだが、薫さん曰く「そんな何分前に言われても無理!」らしい。要は「サプライズを楽しめる」というタイプの人選が大切ということか。  一方「ありきたりじゃつまらないし、ネットで例文を検索している際に『こんな方法もあるのか!』って思って取り入れました」という幸恵さん(30歳)が行ったスピーチは「手紙形式のスピーチ」というもの。  「○○ちゃんへ みたいな感じで新婦の友人にお手紙を書いて読み上げるやり方です。これなら多少フランクな書き方でも大丈夫だし、何より暗記しないで堂々と読み上げることができますよね。読んだものはそのまま友人にあげれば一応記念にもなります」(幸恵さん) なるほど、確かにこれなら読みあげればいいだけなので、人前で話すのが苦手な人でも失敗しないかもしれない。  主役はあくまで新郎新婦ながらも、いざとなると緊張し、内容もあれこれ考えて、こっそりリハーサル……そんな人知れず頑張るスピーチ担当独女たちにも幸あれ(高山惠)  1   0   0   0   0   0   0   0   0
dokujo-tsushin-4778031.txt   携帯電話が普及する以前、恋人への連絡ツールは一般電話が普通だった。恋人と別れたら、手帳に書かれた相手の連絡先を涙ながらに消す。そうすれば、いつしか縁は切れていったものである。しかし現在は、携帯電話がありメールがあり、インターネットを開けば、ブログで相手の晩飯までわかってしまう赤裸々なご時世。切っても切れない元カレとの縁に独女たちは何を思うのであろうか?  「5年前に別れた彼からメールが届いてビックリしました」とは尚美さん(36歳)  「彼の浮気が原因で別れたのですが、現在は独り身らしいことが書いてありました。ただ、私には婚約間近の恋人がいるのでスルー。もし自分に相手がいなかったら、復活愛はあったかも。出会いの機会が少ない独女にとって、いい時代と言えるのでは?」  彼と交際していた当時、尚美さんは実家に住んでいた。もしもメールも携帯電話もない時代だったら、恐らく彼からの連絡はあり得なかっただろう。  一方、美加子さん(38歳)は「一般電話だけの時代のほうが、縁を切りにくかったですよ」という。  「今はメモリ頼りになっている分、電話番号やメールアドレスを消去してしまえばそれまでってところがありますからね。ずるずる引きずろうと思えば引きずれるし、切ろうと思えば切れる。ひと昔前は彼の電話番号を暗記していたものです。受話器を上げたり戻したり……気持ちを断つのが難しかったなぁ」  知恵さん(34歳)も同意見だ。  「情報は自分が情報網を使えば入ってくるが 自分次第でシャットアウトできるもの。だけど私は、“別れた彼と絶縁すべき”とは思っていません。心が癒されるまでの期間は連絡を断ちきり、それ以降はメールを送るなどして、友達関係に戻ることが多いですね」  オール・オア・ナッシングだった以前に比べ、今は縁を切る、友人に戻る、メル友関係を続けるなど、別れた後の関係性を選択できるようになった。未練が残っているうちは辛いが、ツールを上手く使えばメリットを得られることもあるだろう。ただし、落とし穴もある。最後に、律子さん(35歳)のトホホな話を紹介。  「10年前につきあっていた元彼とは、節目節目にメールをしています。“マイミク”で日記にコメントを書き込んだりもするし、年賀状もやりとりする仲。元彼はすでに結婚して子どもが二人いるんですね。最近はすっかり中年太りしてきてマイホームパパって感じ。いい人ではあるけど、すっかり気持ちが冷めた今となっては、なぜ自分があれほど彼に執着していたのか疑問に思えてくる。過去の恋愛の想い出をきれい残したいのなら、知らないほうがいいこともあるかもしれません」  恋の思い出は脳内で美化されるもの。ネットなどで友情関係を続けるのはよいが、同時に淡く切ない恋の思い出は生活感、現実感にまみれてしまうことがあるので、繋ぎすぎには注意したいところ。ま、お互い様ですけどね。(来布十和)   1   0   0   0   0   0   0   0   0
dokujo-tsushin-4782522.txt   「男性はやっぱり、女性の“すっぴん”が大好きなんですかね」と不満そうに話すのは、出版関係で働く香さん(仮名/31歳)。というのも、最近ブログにすっぴん写真を掲載する芸能人が多く、それがニュースになり話題になることがあるからだ。  今年に入ってから、“すっぴん”をブログで披露した芸能人は、小倉優子、安倍なつみ、モーニング娘。の田中れいな、優木まおみ、仲里依紗など、年齢も活躍しているジャンルも様々。私生活をリアルタイムに発信できるブログだからこそ、皆それぞれにリラックスした表情で自分のすっぴんを公開している。ファンにとっては、好きな芸能人の素顔が垣間見れる嬉しいサービスなのだろう。  では、なぜ芸能人のすっぴん顔披露に、彼女は疑問を抱いたのだろうか。「私のひがみだと言う事は重々承知なんですけど、“随分自分に自信があるんだな”って、素直にその美しさを認める事が出来なくて…」と話す香さん。「コメントに“すっぴんでもかわいい!”とか、“メイクしなくても全然OK!”とか賞賛ばかりが並ぶのを見越して、すっぴん写真を公開してるんだなって思うと何か複雑ですね」と付け加えた。  本来ファンサービスである為のすっぴん披露を、「話題を呼ぶ為や、コメントで褒められたいから」行っているのでは? と、独女はつい“ナナメ”に見てしまう様だ。また、メーカーで営業をしている裕美さん(仮名/32歳)は「男性の“すっぴん幻想”には参りますね。そりゃ素顔がキレイならば私だってすっぴんで出社しますよ。でも、毎日少しでもキレイになりたいと一生懸命メイクしている努力も認めて欲しいな」と独女なりの乙女心を明かしてくれた。  「10代や20代前半の若い女の子がすっぴんを載せているのは、“ああ、やっぱり可愛いな”と心から思えるんですけど、私と同年代の人が披露していると自分のすっぴんと比べてゲンナリします」と、美しい芸能人すっぴんを見た後に独女達は人知れず傷ついているのである。  さて、芸能人のすっぴん披露、実際に男性の評判はどうなのだろうか。アパレル企業に勤める雄介さん(仮名/34歳)は「個人的に女性のメイクした顔に魅力を感じないから、すっぴんを見るとすごく可愛いと思う」と賛成派。一方、IT企業で働く徹さん(仮名/28歳)は「人によるけど、何でわざわざブログに載せるんだろうとは思います。本来、女性のすっぴんは大切な相手にだけ見せて欲しいんですよ。“あ、俺だけに見せてくれた”って感じで(笑)」と男性陣の意見もそれぞれの様だ。  今後、ブーム化する予感もあるブログでのすっぴん披露。肯定派と反対派に分かれている様だが、男性が女性の“すっぴん”に特別な想いを持っている事は確か。独女達も、いつかすっぴんを披露するその時の為に、素顔を磨く必要があるのかもしれない。   1   0   0   0   0   0   0   0   0
dokujo-tsushin-4788357.txt   ヒップの加齢による変化は「たわむ→下がる→内に流れる」、バストは「そげる→たわむ→外に流れる」という。バストの変化はすでに20代から始まり、20代にして「たわむ」になっている人もいる。そして、元に戻った人は一人もいない。さらに、体の各部位の20代〜50代までの変化をみると、ウエストとお腹の変化が最も大きく、お腹はバストと同じ大きさになっている。  これは、4月に開催されたワコール人間科学研究所の記者発表「からだのエイジング(加齢による体型変化)について一定の法則を発見」での内容の一部。延べ4万人分の経年変化の数値を集計・分析したデータとともに、写真や映像で説明させるので説得力は抜群だ。  現実を直視させられた後に、体型変化の少ない人達の身体的特徴や日常の行動・意識を紹介。その主な内容は、日頃から体を動かし、姿勢をチェック、下着は必ず試着してフィット感を確かめるというもの。そして、パネルディスカッションでは、歩幅の広い歩き方を1年間続ける実験に参加した人が、背筋が伸び、脂肪が落ちたという結果などが紹介されていた。  興味は尽きず、知人たちに内容を伝えるとさまざまな意見や経験が聞けた。  「ずっと計測されているから、体型変化の少ない人はスポーツをしてたのでは?」という疑問もあったが、この回答は、「運動を一生懸命しているというより日常生活を気をつけている印象が強い。そして、ダイエットはあまりしたことがない」とのこと。  「叔母もそんなことを言っていた」と言うのはY子。60歳代の叔母さんが友人たちと温泉旅行に行ったとき、「バストの変化が少ないとほめられた」と喜んでいたので、バストのケア方法を尋ねたそうだ。「叔母はブラジャーを常に着用し、購入時は必ず計測して試着している。一方、友人達は『苦しい』からと家ではブラジャーをしないこともあるらしい」。それを聞いて以来、Y子は下着を買うときには試着はもちろん、計ってもらうようにしている。  「私も歩いてやせた」と話すのは、腰痛に悩まされていたK子。医師に筋力の低下を指摘されて、駅までの自転車を止めて、片道30分の道のりを毎日往復歩くことに。筋力をつけるために始めたことで体全体が引き締まり、結果として減量にも成功した。  「でも、スポーツすればしまるよね」と言うA子は、不摂生がたたって気になり始めたウエスト回りをスポーツクラブに通って改善。ジーンズがワンサイズ小さくなったと喜んでいる。  パネルディスカッションでは、「加齢は一方通行だが、現状維持は可能」「アンチエイジングは医学界でも注目だが、身体的な美しさの維持と健康維持の関係性は表裏一体のはず」とも言われていた。それならば、体型変化という加齢への抵抗はあきらめないほうが得策だ。 杉本彩が言っていたっけ、「若いころに戻りたいとか、若く見られたい、とは思わない。今の自分がどう美しくあるかを追求したい」って。(オフィスエムツー/オオノマキ) 詳細はコチラ    1   0   0   0   0   0   0   0   0
dokujo-tsushin-4788362.txt   6月から支給される子ども手当だが、当初は子ども一人当たり月額2万6000円が支給されるはずだった。ところが、初年度は半額支給となり、さらに2011年度以降も子ども一人当たり月額2万6000円の支給は見送られそうだ。  先日は在日外国人男性がタイで養子縁組をしたと称する554人分の子ども手当を申請しようとして市から却下されたニュースが報じられたが、悪い人間がちょっと考えれば簡単に不正ができるような不備だらけの子ども手当って、一体どうなっているの? と支給されない側の独女からも疑問の声が聞こえる。  現在独身の由梨さんは、「私立の幼稚園にベンツで送り迎えをしているような家にどうして子ども手当が必要なの?」と一律支給にはどうしても納得できないと訴える。    「子ども手当はフランスの真似をしたと聞いていますけど、フランスでは子ども手当は“家族手当”といい所得制限はありません。でも家族手当が貰えるのは第2子からで20歳まで支給され、3人目からは割増の家族手当が貰えるそうです。子ども手当が少子化対策を目的にしたものなら、フランスのように2人目から手当を出すべきではないですか?」  一律支給だけをフランスの真似をするのはおかしいという。  それに少子化対策と言われながら、子ども手当を当てにして出産しようという声は聞かない。  「政権交代をすればなくなるかもしれない手当を期待して、今から結婚してもすぐに妊娠するとは限らないし、無事出産の暁には子ども手当は廃止されているかもしれないですよね」  その可能性もなきにしもあらずだ。  子ども手当の使い道について子どものいる主婦に聞くと、将来の教育費のために貯蓄に回すという人が多かった。それについても、  「子どもが欲しくてもできなかった家庭がその費用を負担するのはとてもお気の毒な気がします。それに本当に子どものために使われるのならいいのですが、親がギャンブルに使ったり、親の遊興費に使われるために私たちの税金を使ってほしくないですね」と由梨さん。  バツイチの綾さんは、「子どものいない夫婦も、独身も、働いて税金を納めることで次世代を担う子どもたちを育てることに貢献する。それが子ども手当だと思っていましたが、子どものいる家庭にいくはずのお金がどんどん減らされ、それがどこへ行くのかわからないし、申請書の偽装で、私たちの税金が外国人の子どものところに行くのは納得ができません」と制度の不備に怒っている。    「所得制限限度額のある児童手当を増額するべきなのに、全世帯平等に子ども手当てをばらまくのは選挙のための人気とりしか思えません。これで政権が変われば子ども手当はどうなるのか?」  もしこのまま子ども手当をばら撒かれれば、将来子ども手当をもらった子どもたちが増税という形でつけを払わされるのではと綾さんは心配もしていたが、財政難を地方に泣きつく地方負担に地方自治体から反発の声が上がっている。  一体どうなってしまうのか? 今後の子ども手当をしっかり見守りたい。  ところで今回、子どものいない独身の人たちに意見を聞いたのだが、「子ども手当」は自分たちには関係ないのでよく分からないという独女が多かった。  介護保険についても、実際自分が親の介護をする立場になって初めて内容かを知ったという人が多いのだが、どんな制度も国会を通過して施行されれば私たちの納めた税金が使われるのだ。知ることも文句を言うことだって私たちの権利だと思う。無関心でいるよりはよほどいいのではないだろうか。(オフィスエムツー/佐枝せつこ) 1   0   0   0   0   0   0   0   0
dokujo-tsushin-4788373.txt   書店で偶然『うさぎのくれたバレエシューズ』(小峰書店 安房直子/著、南塚直子/イラスト)という絵本を見つけたモトコさん(27歳 薬剤師)は、懐かしさと嬉しさで胸がいっぱいになった。  「バレエを習っていた私は、この絵本を読むと励まされる気がして、小学校の図書室で何度も読みました。どうしても欲しくて母と近所の書店を探したんですけど見つけられなくて…」とモトコさん。優しいピンク色が印象的な『うさぎのくれたバレエシューズ』は、表紙が見えるように今モトコさんの部屋に飾られている。  広告代理店に勤務するマサエさん(40歳)のお気に入りは『100万回生きた猫』(講談社 佐野洋子/著)。小学生の頃、図書館で頻繁に借りていた本だ。「6年生になって、周りの子が厚い小説を読んでいるのに、私は相変わらず『100万回生きた猫』を読んでいました。母から『もっとちゃんとした本を読みなさい』って注意されたこともありましたが…。今なら、母に『これは特別な本よ』と言えます。当時も子どもなりに絵やストーリーから、いろいろなことを感じていたんでしょうね」(マサエさん)  絵本の穏やかストーリーや柔らかな絵に癒される女性は多い。周囲の女性たちに聞いてみると、大人になってから購入した絵本は、新しく出版されたものより「子ども時代に読んだ本」や「特別な思い出がある本」が多いようだ。美しい絵が印象的な『ごんぎつね』(偕成社 新美南吉/著、黒井健/イラスト)や『てぶくろを買いに』(偕成社 新美南吉/著、黒井健/イラスト)、ちょっとクセのあるサンタが登場する『さむがりやのサンタ』(福音館書店 レイモンド・ブリッグズ/著、すがはらひろくに/翻訳)なども人気が高い。懐かしい絵本を開くとき、忘れていた子ども時代の「感性」がふと蘇えるのだろう。  大人になってから絵本の魅力を発見した人もいる。子どもの頃、絵本にはほとんど感心がなかったナオミさん(36歳 メーカー勤務)が絵本に惹かれたきっかけは、友人のお子さんにプレゼントした『ぐりとぐら』(福音館書店 なかがわりえこ/著、おおむらゆりこ/イラスト)。  「絵も可愛いし、大きなカステラは美味しそうだし、何より『ぐりぐら ぐりぐら』という言い回しに、はまっちゃいました。『ぐりぐら ぐりぐら』ってつぶやくと、ちょっとくらい嫌なことがあっても、どうでもよくなっちゃいます(笑)」(ナオミさん)  読んで癒される絵本だが、最近は、自分で絵本を描いてみたいと思う女性も増えているらしい。大阪で「大人のための絵本講座」を開いているイラストレーターのおおさわまきさん(星未来工房)に、絵本を描く魅力について伺った。  「絵本は目でイメージしその世界に入り込める奥深いものです。文章と絵で構成されているので、いろいろな見方ができるし、たくさんのことを伝えられるのが魅力です。絵本講座を受講した生徒さんたちは、一度絵本を仕上げると『もっと作りたい、楽しい!』と目を輝かせますよ。絵本作りは、年齢関係なく誰にでもできる癒しの世界だと思っています」  絵本作りのコツについてお聞きすると「私が絵本作りの勉強し始めた頃、先生から『難しく考えたらダメだよ』と繰り返し言われました。難しいと思うとどんどん描けなくなるんですよね。だから、自分も含めて、難しくないことからはじめていこうと強く思いました。そして、何よりも童心に戻ることが大切です。子どもは何でも素直に楽しむでしょう。大人も『恥』とか『かっこよく』とか考えないで、遊び感覚で自然に絵本作りに取組むことが大切です」(おおさわさん)。  子どものように素直に描けるようになると、考え方も自然と柔軟になってくるはず。大人という枠組みや常識という枠組みから離れて、自由に空想し、自由に描くことで、心が癒されていくのだろう。  最後に、おおさわさんにお勧め絵本を紹介していただいた。「『ちきゅうになった少年』(フレーバル館 みやざきひろかず/作・絵)が大好きです。毎日忙しくストレスをかかえる人にとって、人間でないものに生まれ変わってみたいという願望をおもしろく表現していると思います。疲れたとき、辛いことがあったとき、逃避したいとき、心を休める1冊です。また、水彩画は脳や心を緩め、癒してくれる画材なのでとてもお勧めですよ」(おおさわさん)  絵本を読んでみたいが、どんな本が自分に向いているかわからないという人は、まず図書館の絵本コーナーへ行って見るといい。何冊も手に取る間に、自分の好みの絵やストーリーに出合えるはず。読み終えたとき気持ちが前向きになれる本がいい。(オフィスエムツー/神田はるひ) ・取材協力 -星未来工房 おおさわまき 1   0   0   0   0   0   0   0   0
dokujo-tsushin-4788374.txt   昨年の秋、希望の職種に転職したカナコさん(30歳/ 商社勤務)。やりがいのある仕事を得て充実した毎日を送れるだろうと思っていたのだが、思いがけない問題に悩んでいる。  「女性社員は休憩室で一緒にお昼ご飯を食べるのですが、そのときの話題が社内の噂話や悪口ばかりで驚いています。社内不倫の話から男性社員の品定め、他の支店の女性社員の悪口など、毎日毎日よくネタが尽きないものだと感心するくらい。うんざりしています」(カナコさん)  もちろん女性でも社外に食べに行く人もいるが、後で先輩女性から嫌味を言われたり、根も葉もない噂を立てられたりということも…。「お昼休みが近づくと憂鬱になります。30代になって、お昼休みのことで悩むとは思ってもいませんでした」(カナコさん)  忙しい一日の中で、唯一休息できるのがお昼休みという人も多いはず。気の合う仲間と美味しいお弁当やランチサービスを食べ、楽しい会話ができたなら、午後の仕事も頑張れるだろう。でも、思い通りにならないことも多い。  ムツミさん(29歳 医療関連)の再就職先は、女性社員はムツミさんを入れて4人だけ。長い間一緒に働いている女性3人の結束が固いのが問題だ。「休憩室が一箇所なので、お昼は一緒に食べるのですが、先輩3人の仲が良すぎて、私は話題に入れません。最初は黙って話を聞いていたのですが、だんだん居づらくなって…。今は食べ終わったらすぐに机に戻って雑誌を読んでいます」(ムツミさん)  この会社では、新しく女性社員を入れても短期間で辞めてしまうことが多いという。1人でお昼休みを過ごせるムツミさんを見て「長く勤めてもらえるかもしれない」と上司は期待しているらしいが…。  派遣社員のエリさん(27歳)は、以前は「1人でお昼休みを過ごすのは辛い」と感じていたが、派遣社員になり複数の会社を経験するうちに「1人の気楽さ」に目覚めたという。  「たまに同じ課の人と社外に食べに行くこともありますけど、雑誌を見ながら自分の机で食べることが多いですね。後はメールを書いたりして過ごしています。今の派遣先は、女性同士の束縛がないのでとても気楽です(笑)」(エリさん)  エリさんの話によると、お昼休みに皆で『昼ドラ』を見る会社もあるという。ドラマ好きのエリさんはそれなりに楽しかったが、中には、先に席をたって給湯室で時間をつぶしている女性社員もいたそうだ。  「会社によってお昼休みの過ごし方はだいぶ違います。女性社員は必ず一緒に食べるという暗黙のルールがある会社では、それぞれ黙って携帯を見ながら食べていましたよ。7〜8人いるのにシーンとしているんです。これはかなり辛かったです。あとは、一番年上の女性社員の方が話好きで、お昼休みの間中は、ひたすら皆で彼女の話を聞かなくてはいけないという会社もありました」(エリさん)  小学生の頃、遠足の前になると教室のあちこちで「○○ちゃん、一緒にお昼を食べようね」という約束が取り交わされていた。いつも私は、ドキドキしながら友だちのOKを待っていたように思う。先生は内気な子を心配して、リーダー格の生徒に「お昼には○○ちゃんも誘ってあげてね」などと根回しをしたり、「今回は皆で食べましょう」と声をかけたり…。  高校に入学したばかりの姪は「すぐにお昼を食べる友達ができて良かった」と嬉しそうに話してくれた。幾つになっても、お昼休みを誰とどこでどう過ごすかは大きな問題なのだ。  余談になるが、禁煙のオフィスが増えている昨今は、喫煙派のお昼休みの過ごし方も変わってきている。知人の勤め先では、今春からビル内に喫煙できる場所が無くなったため、仕方なく最寄り駅の喫煙所まで煙草を吸いに行くという。  「タバコを吸うためだけに、喫煙できるカフェに毎日行くわけにもいかないですし、室内で吸っていると洋服に煙草の臭いが染み付くので、今は駅の屋外の喫煙場所がありがたいです」と知人。雨の日の昼休みは、駅までの道のりを考えると憂鬱になるらしい。(オフィスエムツー/神田はるひ)  1   0   0   0   0   0   0   0   0
dokujo-tsushin-4788388.txt   「彼の収入が少ないから私も働かなければならないし、それを思うと結婚はもう少し先でもいいかな」と結婚を躊躇する独女がいる。彼女は彼の収入だけで暮らせるのなら、仕事は今すぐにでも辞めたいらしい。つまり専業主婦志望なのだが、彼の年収を聞いて首を傾げた。  この金額で本当に生活ができないのだろうか?  かつて専業主婦が多かった時代、主婦の働き先はなく、今月もかつかつだとこぼしながらも、夫の稼ぎだけで暮らしていた家庭が多かった。しかし今は不況で夫の収入が減ったとはいえ、外食、ブランド品購入、安いツアーとはいえ海外旅行にも行っている。食べるだけで精一杯の昔に比べれば、ものすごく贅沢ではないだろうか?    成人した二人の子供がいる専業主婦の紀世子さん(56 歳)は、「今は専業主婦がセレブのように言われますけど、私はブランド品も持ったことがなければ、家族で海外旅行にも行ったことがないんですよ。夫の収入だけで充分とはいいませんけど、贅沢さえしなければ毎月何とかなったものです」という。    子供が小学校に入学すると、塾の費用を捻出するためにパートに行く主婦もいたが、紀世子さんの家庭はご主人の方針で塾には一切通わせず、兄は水泳、妹は習字と、週に一度の習い事に通わせただけだそうだ。  「私立中学受験で塾に通わせているご家庭は大変そうでしたよ。塾の費用が一か月5万円と聞いてびっくりしました。そこまでして私立に行かせて、その後も莫大な教育費がかかるのに大変だとあと思いました」  紀世子さんの長女は私立の女子大学に入学したが、中学・高校から持ち上がりできた友人には小学校の時の同級生もいる。「中高一貫教育の必要性はよく分かりませんが、結局同じ大学に通うなら何も高い教育費を払って中学から行く必要がないのでは?」これは私の考えですがと紀世子さん。  仕事に生きがいを持ち自分のために働いている主婦もいるが、家族で海外旅行に行ったり外食をしたり、生活水準を上げるために働いている主婦もいる。自分の稼ぎでブランド品を買う主婦もいるが、やはり主婦の働く目的の大半は子供の教育費の捻出だろう。  教育費は、子どもが生まれてから大学卒業まで一般に1000万円以上もかかると言われている。幼稚園から大学まで私立なら2000万円は超す。となれば教育費のために働かなければならないわけだが、幼稚園から私立にやるのはどうしてなのだろうか?  「子供に誇れる学歴をつけてやりたいからです」  私立幼稚園入学を目指している幼児の母親、A子さんはいうが、誇れるとはすなわち母親の価値観で、他の子と比べて自分の子供は特別なことをさせているという母親自身の見栄もあるのかもしれない。 子供を私立幼稚園に行かせたり、ブランドの服を着せたりすれば、母親もそれに見合う服装やバックを身につけなければならなくなる。    そういう生活がしたいけれど、夫の収入でできなければ、我慢すればいい。我慢できなければ働けばいい。けれど、働く目的が子供のためであるなら、なにが本当に子供にとって幸せなのかを考えるべきではないだろうか。  彼の収入が少ないとか夫の稼ぎが足りないとこぼす女性たちの胸の内は、なくてもいいものをあえて欲しがる暮らしを求めている気がする。 人と競い合うことで向上することもあるが、家庭における幸せとは決して比べたり競い合うものではないと思う。  前述の紀世子さんだが、学校から帰ってくるといつも「お帰りなさい」と待っていてくれるお母さんがいてくれて嬉しかったと成人した娘さんから言われたそうだ。 「能力も資格もないので家にいて節約しているだけの生活でしたが、子供と過ごせた時間は楽しかったですよ」    養ってくれた夫にも感謝しているという紀世子さんの言葉がものすごく新鮮に聞こえた。  働いて得るものもあるが、節約して作った時間で得るものもある。彼の収入が少ないと思うのなら、やりくりという算段を覚えることをしてみてはどうだろうか? 結婚はいろいろ頭で考えているより、実際生活をしてみればなるようになるものです。(オフィスエムツー/佐枝せつこ)  1   0   0   0   0   0   0   0   0
dokujo-tsushin-4791665.txt   これからの季節、お肌の天敵と言えば“紫外線”。マーケティング会社トレンダーズ株式会社が、20、30代女性に「UVケア」に関する意識調査を実施した所、99%の人が「外出するとき、UVケアが必要」と回答。もはや、UVケアは女性にとって常識となっている事が分かります。アンチエイジングを目指す独女にとってもUVケアを見逃す事はできません。  「紫外線が気になるのは、1日のうちどんなシーンですか?」という質問に対しては、最も多く挙がったのが「通勤時」で、半数以上が回答。「紫外線が気になる時間帯」については、最も多かったのが、「12時〜15時」で83%。次いで「9時〜12時」が67%、「〜9時」(43%)と、働く女性がUVケアを意識するのは、朝の時間帯だという事が分かります。  実際、「朝にUVケア」をしているのが87%にのぼり、「朝の通勤時間が一番紫外線を浴びる。(36歳・不動産広告デザイン)」「通勤時に日やけをしてしまうので欠かさずしている。(29歳・商社経理)」と、日焼けやシミを防ぐ為には“朝のUV”ケアがマストの様です。  具体的なUVケアの方法としては、最も多かったのが「日やけ止めを塗る」で、全体の92%が回答。次いで、「日傘」(59%)、「帽子」(39%)と続いています。手軽に塗れてしっかりUV対策ができる「日やけ止め」が女性の支持を集めました。  「日やけ止めは、1日に何回塗り直しますか?」という質問に対しては、平均で「0.94回」と、およそ1日1回塗り直していることが明らかに。汗をたくさんかいた時はもちろん、知らず知らずのうちに効果が低下しているのが不安で、つい何度も塗りなおしてしまいますが、日々忙しい、独女にとってはその時間すら惜しい所。また、肌への負担も気になります。 また、「日やけ止めに求めるものは何ですか?」という質問によると、「日やけ止め効果」(93%)という日やけ止めにとって、マストの効果となる回答に次いで「肌への負担の少なさ」(88%)、「ベタつかないこと」(73%)と意見が多く、ただUVケアが出来る事だけでは無く、“お肌に優しいこと”が重要になってくる様です。  そんな、UVケアと肌への優しさ両方を大切にしたい女性にオススメしたいのが、新しくなった日やけ止め「アネッサ」。地上のあらゆる紫外線をカットしてくれるだけでは無く、今までの日やけ止めにありがちだった、べたつきや白浮きが無く、サラサラの使い心地です。最近、紫外線をジリジリとお肌に感じながらも日やけ止めを使うことで「肌の負担になるのは嫌」と、使い損ねていた独女の皆さんは、ぜひ試してみては?詳しくはこちら ・アネッサ - 資生堂  1   0   0   0   0   0   0   0   0

続いて、データフレームとして読込み、学習データ、検証データ、評価データに分割しておきます。

import pandas as pd
from sklearn.model_selection import train_test_split
from tabulate import tabulate

# データの読込
df = pd.read_csv('./text/livedoor.tsv', sep='\t')

# データの分割
categories = ['dokujo-tsushin', 'it-life-hack', 'kaden-channel', 'livedoor-homme', 'movie-enter', 'peachy', 'smax', 'sports-watch', 'topic-news']
train, valid_test = train_test_split(df, test_size=0.2, shuffle=True, random_state=123, stratify=df[categories])
valid, test = train_test_split(valid_test, test_size=0.5, shuffle=True, random_state=123, stratify=valid_test[categories])
train.reset_index(drop=True, inplace=True)
valid.reset_index(drop=True, inplace=True)
test.reset_index(drop=True, inplace=True)

# 事例数の確認
table = [['train'] + [train[category].sum() for category in categories],
         ['valid'] + [valid[category].sum() for category in categories],
         ['test'] + [test[category].sum() for category in categories]]
headers = ['data'] + categories
print(tabulate(table, headers, tablefmt='grid'))
--- 出力 ---
+--------+------------------+----------------+-----------------+------------------+---------------+----------+--------+----------------+--------------+
| data   |   dokujo-tsushin |   it-life-hack |   kaden-channel |   livedoor-homme |   movie-enter |   peachy |   smax |   sports-watch |   topic-news |
+========+==================+================+=================+==================+===============+==========+========+================+==============+
| train  |              696 |            696 |             691 |              409 |           696 |      673 |    696 |            720 |          616 |
+--------+------------------+----------------+-----------------+------------------+---------------+----------+--------+----------------+--------------+
| valid  |               87 |             87 |              87 |               51 |            87 |       84 |     87 |             90 |           77 |
+--------+------------------+----------------+-----------------+------------------+---------------+----------+--------+----------------+--------------+
| test   |               87 |             87 |              86 |               51 |            87 |       85 |     87 |             90 |           77 |
+--------+------------------+----------------+-----------------+------------------+---------------+----------+--------+----------------+--------------+

学習の準備

BERTモデルを利用するためにtransformersライブラリをインストールしておきます。transformersを通じて、BERT以外にも多くの事前学習済みモデルを短いコードで非常に簡単に利用することができます。

!pip install transformers["ja"]

モデルの学習と評価に必要なライブラリをインポートします。

import numpy as np
from transformers import AutoModel, AutoTokenizer
import torch
from torch.utils.data import Dataset, DataLoader
from torch import optim, cuda
import time
from matplotlib import pyplot as plt

続いて、今回利用する日本語事前学習済みBERTモデルを指定します。 transformersで公開されている東北大学の乾・鈴木研究室のモデルのうち、bert-base-japanese-whole-word-maskingを試すことにします。

# 事前学習済みモデルの指定
pretrained = 'cl-tohoku/bert-base-japanese-whole-word-masking'

次に、データをモデルに投入可能な形に整形します。

まずは、PyTorchでよく利用される、特徴ベクトルとラベルベクトルを合わせて保持するDatasetを作成するためのクラスを定義します。 このクラスにtokenizerを渡すことで、入力テキストに形態素解析などの処理を行い、指定した最大系列長までパディングした上で単語IDに変換する処理を実現できるようにしておきます。

とはいえ、BERT用にすべての処理が書かれたtokenizerそのものは、のちほどtranformersを通じて取得するため、クラス内で必要なものはtokenizerに渡す処理と結果を受け取る処理のみです。

# Datasetの定義
class NewsDataset(Dataset):
  def __init__(self, X, y, tokenizer, max_len):
    self.X = X
    self.y = y
    self.tokenizer = tokenizer
    self.max_len = max_len

  def __len__(self):  # len(Dataset)で返す値を指定
    return len(self.y)

  def __getitem__(self, index):  # Dataset[index]で返す値を指定
    text = self.X[index]
    inputs = self.tokenizer.encode_plus(
      text,
      add_special_tokens=True,
      max_length=self.max_len,
      truncation=True,
      padding='max_length'
    )
    ids = inputs['input_ids']
    mask = inputs['attention_mask']

    return {
      'ids': torch.LongTensor(ids),
      'mask': torch.LongTensor(mask),
      'labels': torch.Tensor(self.y[index])
    }

上記を用いてDatasetを作成します。

引数の一つであるMAX_LENは最大系列長を表し、これより長い文は切られ、短い文はパディングされることによりこの長さに揃えられます。本来BERTでは512まで指定可能ですが、今回はメモリの制約から128を指定しています。

# 最大系列長の指定
MAX_LEN = 128

# tokenizerの取得
tokenizer = AutoTokenizer.from_pretrained(pretrained)

# Datasetの作成
dataset_train = NewsDataset(train['article'], train[categories].values, tokenizer, MAX_LEN)
dataset_valid = NewsDataset(valid['article'], valid[categories].values, tokenizer, MAX_LEN)
dataset_test = NewsDataset(test['article'], test[categories].values, tokenizer, MAX_LEN)

for var in dataset_train[0]:
  print(f'{var}: {dataset_train[0][var]}')
--- 出力 ---
ids: tensor([    2,  5563,  3826,     7,     9,     6,  5233,  2110,    10,  4621,
           49,  1197,    64,    14, 10266,     7,  3441,  1876,    26,    62,
            8,    70,   825,     6,  9749,    70,  3826,     7,  1876,    15,
           16,  7719,  1549,  4621,    11,  1800,    15,    16,  6629,    45,
           28,   392,     8,  5880,     7,  1800,    34,  1559,    14,    31,
          947,     6,  8806,    16,  6629,    13,  1755,  3002,  4621,    11,
         1942,     7,  9626,   392,   124,     7,   139,     8, 25035,  4021,
          489,  7446,   143, 16430, 13901,  1993,    49,  8365,  2496, 12084,
           40,  5880,  1800,  9749,  1876,    15,    16,  7719,  1549,  4621,
           14,     6,  5563,  3826,     5,  4314,  5233,  2110,    10,   120,
         4118,     7,  1876,    26,    20,    16,    33,   344,     9,     6,
        10843,   329, 11426,    11,  1943,    10,    72,     7, 10485,     7,
         1876,    26,    62, 26813,  7004,    11, 20718,     3])
mask: tensor([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1])
labels: tensor([0., 1., 0., 0., 0., 0., 0., 0., 0.])

1文目の文の情報を出力しています。

入力文字列がidsとしてID系列に変換されていることが確認できます。BERTでは、変換の過程で元の文の文頭と文末に特殊区切り文字である[CLS]と[SEP]がそれぞれ挿入されるため、それらも23として系列に含まれています。 正解ラベルもlabelsとしてone-hot形式で保持しています。 また、パディングの位置を表すmaskも合わせて保持し、学習時にidsと一緒にモデルに渡せるようにしておきます。

続いて、ネットワークを定義します。

transfomersを用いることで、BERT部分はまるごとAutoModelで表現可能です。その後、分類タスクに対応するため、BERTの出力ベクトルを受け取るドロップアウトと全結合層を定義すれば完成です。

# BERT分類モデルの定義
class BERTClass(torch.nn.Module):
  def __init__(self, pretrained, drop_rate, otuput_size):
    super().__init__()
    self.bert = AutoModel.from_pretrained(pretrained)
    self.drop = torch.nn.Dropout(drop_rate)
    self.fc = torch.nn.Linear(768, otuput_size)  # BERTの出力に合わせて768次元を指定

  def forward(self, ids, mask):
    _, out = self.bert(ids, attention_mask=mask, return_dict=False)
    out = self.fc(self.drop(out))
    return out

BERT分類モデルの学習

ここまでで、Datasetとネットワークが準備できたため、あとは普段通りの学習ループを作成します。 ここでは一連の流れをtrain_model関数として定義しています。

登場する構成要素の意味については、【言語処理100本ノック 2020】第8章: ニューラルネットの記事の中で、問題の流れに沿って解説していますので、そちらをご参照ください。

def calculate_loss_and_accuracy(model, loader, device, criterion=None):
  """ 損失・正解率を計算"""
  model.eval()
  loss = 0.0
  total = 0
  correct = 0
  with torch.no_grad():
    for data in loader:
      # デバイスの指定
      ids = data['ids'].to(device)
      mask = data['mask'].to(device)
      labels = data['labels'].to(device)

      # 順伝播
      outputs = model(ids, mask)

      # 損失計算
      if criterion != None:
        loss += criterion(outputs, labels).item()

      # 正解率計算
      pred = torch.argmax(outputs, dim=-1).cpu().numpy() # バッチサイズの長さの予測ラベル配列
      labels = torch.argmax(labels, dim=-1).cpu().numpy()  # バッチサイズの長さの正解ラベル配列
      total += len(labels)
      correct += (pred == labels).sum().item()

  return loss / len(loader), correct / total


def train_model(dataset_train, dataset_valid, batch_size, model, criterion, optimizer, num_epochs, device=None):
  """モデルの学習を実行し、損失・正解率のログを返す"""
  # デバイスの指定
  model.to(device)

  # dataloaderの作成
  dataloader_train = DataLoader(dataset_train, batch_size=batch_size, shuffle=True)
  dataloader_valid = DataLoader(dataset_valid, batch_size=len(dataset_valid), shuffle=False)

  # 学習
  log_train = []
  log_valid = []
  for epoch in range(num_epochs):
    # 開始時刻の記録
    s_time = time.time()

    # 訓練モードに設定
    model.train()
    for data in dataloader_train:
      # デバイスの指定
      ids = data['ids'].to(device)
      mask = data['mask'].to(device)
      labels = data['labels'].to(device)

      # 勾配をゼロで初期化
      optimizer.zero_grad()

      # 順伝播 + 誤差逆伝播 + 重み更新
      outputs = model(ids, mask)
      loss = criterion(outputs, labels)
      loss.backward()
      optimizer.step()

    # 損失と正解率の算出
    loss_train, acc_train = calculate_loss_and_accuracy(model, dataloader_train, device, criterion=criterion)
    loss_valid, acc_valid = calculate_loss_and_accuracy(model, dataloader_valid, device, criterion=criterion)
    log_train.append([loss_train, acc_train])
    log_valid.append([loss_valid, acc_valid])

    # チェックポイントの保存
    torch.save({'epoch': epoch, 'model_state_dict': model.state_dict(), 'optimizer_state_dict': optimizer.state_dict()}, f'checkpoint{epoch + 1}.pt')

    # 終了時刻の記録
    e_time = time.time()

    # ログを出力
    print(f'epoch: {epoch + 1}, loss_train: {loss_train:.4f}, accuracy_train: {acc_train:.4f}, loss_valid: {loss_valid:.4f}, accuracy_valid: {acc_valid:.4f}, {(e_time - s_time):.4f}sec') 

  return {'train': log_train, 'valid': log_valid}

パラメータを設定して、ファインチューニングを実行します。

# パラメータの設定
DROP_RATE = 0.4
OUTPUT_SIZE = 9
BATCH_SIZE = 16
NUM_EPOCHS = 4
LEARNING_RATE = 2e-5

# モデルの定義
model = BERTClass(pretrained, DROP_RATE, OUTPUT_SIZE)

# 損失関数の定義
criterion = torch.nn.BCEWithLogitsLoss()

# オプティマイザの定義
optimizer = torch.optim.AdamW(params=model.parameters(), lr=LEARNING_RATE)

# デバイスの指定
device = 'cuda' if cuda.is_available() else 'cpu'

# モデルの学習
log = train_model(dataset_train, dataset_valid, BATCH_SIZE, model, criterion, optimizer, NUM_EPOCHS, device=device)
--- 出力 ---
epoch: 1, loss_train: 0.0976, accuracy_train: 0.8978, loss_valid: 0.1122, accuracy_valid: 0.8575, 405.6795sec
epoch: 2, loss_train: 0.0468, accuracy_train: 0.9622, loss_valid: 0.0802, accuracy_valid: 0.8942, 405.0562sec
epoch: 3, loss_train: 0.0264, accuracy_train: 0.9822, loss_valid: 0.0688, accuracy_valid: 0.9077, 407.3759sec
epoch: 4, loss_train: 0.0164, accuracy_train: 0.9907, loss_valid: 0.0708, accuracy_valid: 0.9050, 407.4937sec

結果を確認します。

# ログの可視化
x_axis = [x for x in range(1, len(log['train']) + 1)]
fig, ax = plt.subplots(1, 2, figsize=(15, 5))
ax[0].plot(x_axis, np.array(log['train']).T[0], label='train')
ax[0].plot(x_axis, np.array(log['valid']).T[0], label='valid')
ax[0].set_xlabel('epoch')
ax[0].set_ylabel('loss')
ax[0].legend()
ax[1].plot(x_axis, np.array(log['train']).T[1], label='train')
ax[1].plot(x_axis, np.array(log['valid']).T[1], label='valid')
ax[1].set_xlabel('epoch')
ax[1].set_ylabel('accuracy')
ax[1].legend()
plt.show()

bert-ja.png

# 正解率の算出
dataloader_train = DataLoader(dataset_train, batch_size=1, shuffle=False)
dataloader_valid = DataLoader(dataset_valid, batch_size=1, shuffle=False)
dataloader_test = DataLoader(dataset_test, batch_size=1, shuffle=False)

print(f'正解率(学習データ):{calculate_loss_and_accuracy(model, dataloader_train, device)[1]:.3f}')
print(f'正解率(検証データ):{calculate_loss_and_accuracy(model, dataloader_valid, device)[1]:.3f}')
print(f'正解率(評価データ):{calculate_loss_and_accuracy(model, dataloader_test, device)[1]:.3f}')
--- 出力 ---
正解率(学習データ):0.991
正解率(検証データ):0.905
正解率(評価データ):0.904

評価データで90%ほどの正解率でした。

通常はさらに、検証データの精度を確認しながらBERTの層ごとの重み固定有無や学習率等のパラメータを調整することが多いと思います。 今回はパラメータ決め打ちでしたが比較的高精度であり、事前学習の強力さが表れた結果となりました。

理解を深めるためのオススメ教材

参考文献

transformers BERT(公式) BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding, Devlin, J. et al. (2018)(原論文)