ギャン・バギャム・ソルドン

一打粉砕に怒喝の心力を込め、万物を叩き割る剛剣の刃を生み出さん

はてなブログAPIを叩いて記事の本文をtxtに出力する(Python)

はてなブログAPIについてちょっとだけ学んだので備忘録を残しておきます。

自分のブログ記事全ての本文を「記事タイトル.txt」ファイルとして出力することを目指します。

簡単な処理の流れは以下。

APIのルートエンドポイントと認証のに必要なAPIキーを設定
APIを叩いて10記事分の記事情報をXML形式で取得
XMLだと扱いにくいので、辞書を経由してjsonに変換、一度ファイルとして出力
jsonファイルを読み込んで、必要な情報(タイトル、本文、カテゴリ)を取得
⇒カテゴリ名のフォルダを作成し、その配下に「タイトル.txt」を出力
⇒次の記事10件の情報を取得する為に、ルートエンドポイントを更新
⇒更新したエンドポイントを再び叩いて記事情報を取得、異常の手順でtxtに出力
⇒全ての記事を出力するまで繰り返す

 

という感じ。実際のコードは以下。

・コード

import requests
import json as js
import xmltodict
import os

# api のエンドポイントurl を引数にとってxmlを返す関数を定義
def get_hatena_response(url):
key = 'XXXXXXXXXX' #各自のapiキー
# Basic認証でapiを叩く為に、ログインidapiキーをタプルに格納
auth = ('kiui_4', key)
# apiを叩いて返ってきたxmlを返す
r = requests.get(url, auth=auth)
return r

# xml のデータを受け取ってjson ファイルを出力する関数を定義
def xml_to_json(xml):
# xmlを辞書に変換する
dict = xmltodict.parse(xml.text)
# 辞書データをjsonに変換する
json = js.dumps(dict, indent=1)
# 変換したjsonをファイルに書き込む
with open('hatena_response.json', 'w') as fw:
fw.write(json)
fw.close()

# json ファイルを見て記事を出力する関数を定義
def write_hatenablog():
# jsonファイルを開いて読み込む
json_open = open('hatena_response.json', 'r')
json_load = js.load(json_open)

# 次のapiエンドポイントを変数に格納する
next_url = json_load['feed']['link'][1]['@href']

# apiで返された10件の記事について、txtファイルに書き込む
for i in range(len(json_load['feed']['entry'])):
# タイトルと本文を変数にする。ファイル名に使えない記号は置換する
title = json_load['feed']['entry'][i]['title'].replace('/', '_').replace('\"','')
main = str(json_load['feed']['entry'][i]['content']['#text'].replace('<p>', '').replace('</p>', ''))
# カテゴリごとにファイルを生成する
try:
category = json_load['feed']['entry'][i]['category'][0]['@term']
os.makedirs(category, exist_ok=True)
# カテゴリの無い記事は その他 ディレクトリとする
except:
category = 'その他'
os.makedirs(category, exist_ok=True)

# カテゴリフォルダ配下に タイトル.txt ファイルを生成し、本文を書き込む
with open(category + '\\' + title + '.txt', 'w', encoding='UTF-8') as fw:
fw.write(main)
fw.close()
# 次のapiエンドポイントは必要なので返す
return next_url

# api のエンドポイントの url を受け取って、記事を出力する関数を定義
def all_process(url):
xml = get_hatena_response(url)
xml_to_json(xml)
next_url = write_hatenablog()

return next_url

#-------------------- メインの処理 ----------------------------------------
if __name__ == '__main__':
# 最初のapiエンドポイントを設定
first_url = 'https://blog.hatena.ne.jp/kiui_4/kiui-4.hatenablog.jp/atom/entry'
# 最初も10件をtxt化、次のエンドポイントを変数へ
next_url = all_process(first_url)

# 次のエンドポイントが出力できる限り繰り返す
while True:
next_url = all_process(next_url)
# 次のエンドポイントが出なくなったらプログラムを抜ける
if next_url == 'https://kiui-4.hatenablog.jp/':
break
# ---------------------- 終了 ------------------------------------------

・出力
f:id:kiui_4:20200919091351p:plain

f:id:kiui_4:20200919092046p:plain

f:id:kiui_4:20200919091856p:plain
いい感じにできた。

虹ヶ咲学園スクールアイドル同好会 2nd Live! によせて

9月12日と13日、虹ヶ咲学園スクールアイドル同好会 2nd Lve 〜Brand New Story〜、~Back to the TOKIMEKI~ を生配信で見たので、その感想を記す。

いや~~~、色々と複雑な感情が多少あれど、それでもやっぱり楽しかったという感情が大きい。ソロで繋いでいく節々に、ユニット曲を挟む構成は、先を全く予想させないものでワクワクした。*1しかも披露されたのは新曲ばかりで、どこに目をやっても新しいものしかない、非情に見応えのあるものだった。ちなみに僕は Märchen Star でお膝をトントンする鬼頭明里さんが大好きです。1stライブの9人で順々にバトンを繋いでいくようなステージとは違った、新しい虹ヶ咲のライブの形があったように思う。オンラインライブにはオンラインの楽しみ方があるとは分かっていつつも、こんな素晴らしいライブだからこそ、現地で…LVで…と思う気持ちはやっぱり芽生えてしまうのだった。

 

無観客配信と聞いて、僕もかなり不安だった。虹ヶ咲のライブ円盤を見返すと、(ソロなのも相まって)『観客のみんなが居るからステージをこんなにも楽しめる*2』と言っている子が多い印象を受けた。だから、観客の居ないステージで彼女たちがどう振る舞うのか想像出来なかったし、心配な部分もあった。奇しくも、その心配事は杞憂では終わってくれなかった訳だ。特に相良ちゃんは自己紹介の『キュンキュンさせちゃうぞ♡』の言い方から既に普段のテンションに入れてない感じがあった。

1万を超える視線が誰か1人に注がれ、爆音が鳴り響き、人々が熱狂する。そんな圧倒的な非日常が人間をキャラクターに変えていくし、キャストのテンションを、パフォーマンスを更に押し上げてくと思わざるを得なかった。その一方で、大西さん、村上さんの堂々とした立ち振る舞いは本当に頼もしかった。

今までのライブに比べてミスの多い、またミスに気付きやすい環境であったことは事実だが、それでもこのライブは絶対にやって良かったし、見て良かったと思う。数々の痛みを伴うライブだったが、その痛みは彼女たちを今後、更に役者として一歩高い場所へ導く糧になるかもしれないし、とにかく、彼女たちの歩みをこんな場所で止めてはならないと強く感じた。振り返れば歴史の1ページだ。ただ真っ直ぐに突っ走ってほしい。

10月にはアニメが始まり、来年には3rdライブがある。不安が全くない訳では無いが、自分なりにちゃんと楽しみたいと思う。という訳で皆さん、『村上奈津実のなっチャンネル』への入会を、どうぞよろしくお願いします(?)

*1:ラブライブのライブ、ユニットが来るとユニットゾーンになってセトリが予測できがち。

*2:意訳

虹ヶ咲学園スクールアイドル同好会の魅力とその変遷について

虹ヶ咲2ndライブまでに自分がどう好きだったのかを、その歴史と共に書き残しておく。

 

・活動初期

虹ヶ咲が結成されてからスクスタがリリースされるまでの間、虹ヶ咲の活動は主にラジオ、生放送、動画への出演が主体だった。その中でも一際目を引いたのが、Youtubeで展開されていた動画企画だ。過去の記事でも何回か言及しているが、私はこの動画企画がとても好きだった。

カットや字幕を駆使して、面白さをコンパクトに纏めた動画には、ラブライブが主に用いる生放送という媒体には作れない楽しさが詰まっていた。動画の内容は主にゲーム実況だったが、その実況対象は携帯用アプリゲームから、据え置き機、ボードゲーム、独自に開発したゲーム(シャンシャンゲーム等)など多岐に渡り、見ていて飽きなかった。彼女たちが遊んでいたゲームを自分たちも遊べることは、数ある魅力の中の一つであると共に、彼女たちに親近感を抱く一因にもなっていた。

動画への出演を通して仲良くなっていくメンバーを見るのも楽しみだった。ゲームでバチバチにぶつかり合う光景も、和気藹々と盛り上がる光景も、なくてはならないものだった。スクフェス分室の動画の最終回の挨拶で、前田佳織里さんが不意に泣き出してしまうシーンは、私が虹ヶ咲を追ってきた中でも一二を争うくらい歴史的な瞬間だった。

Youtubeの動画はスクスタの宣伝が主な目的であった為、スクスタがリリースされた今、動画を作ることに大きな利点は見い出せないが、それでも私は虹ヶ咲のメンバーがバラエティ等の企画でバチバチにやり合う姿を今でも見たいと思っている。ただその反面、才能溢れる彼女たちを、この動画企画という小さなステージに閉じ込めておくことの勿体なさも同時に感じていた。

 

・マッチングフェス~現在

Youtubeでの動画企画が終了してから、虹ヶ咲の活動は大きく変わっていった。画面の中で可愛く喋る声優さん達は、次第にステージを作り上げる一人の役者として売り出され始めた。マッチングフェスや1stライブが行われた2019年がその過渡期だったように思う。虹ヶ咲の展開はライブや生放送を主体とした、従来のラブライブのやり方を踏襲するようになったが、虹ヶ咲の魅力そのものは、μ'sやAqoursとは違う、独自のものへと昇華していった。

虹ヶ咲の見せるステージの最大の特徴と言えば、やはりそれは『ソロ』でのステージングだろう。これこそが虹ヶ咲のステージを、虹ヶ咲たらしめている。どこまでもキャラクターに寄り添った曲、詩、演出等のギミックは、個々のキャラが持つ世界を十二分に表現してくれる。私は最初、『ソロ』であることの意味や魅力をこう捉えてしかいなかったが、いざ蓋を開けてみると、ソロの魅力はもっと別のところにもあった。

ソロでありグループでもある。ライバルであり仲間でもある。私にとって虹ヶ咲の魅力の大部分を占めるのは、こんな概念だ。9人でステージに立つことでは感じ得ない、ソロであるが故の緊張感やプレッシャーは、彼女たち一人一人の前に大きな壁として立ちはだかるが、虹ヶ咲の9人はこの壁を互いに手を取り合って越えようとする。誰かが折れそうになったら、誰かが励ます。誰かの頑張りが、誰かの刺激にもなる。こうして9人で支え合う彼女たちの姿に私は何度もやられてきた。

それでも結局は、ステージの上で一人になってしまう。だが、ある人は舞台袖から仲間のステージの成功を祈っていたり、またある人はファンと同じように仲間のステージを楽しんでいたりする。ソロだからこそ、ステージの外で、私達の見えない場所で強く繋がっている。この「見えない繋がり」こそが、ソロでステージに立つことの、ひいては虹ヶ咲学園スクールアイドル同好会の魅力であると私は思うのだった。

 

以上。虹ヶ咲2ndライブがとても良いライブになるよう祈りながら、今日は眠りにつくとする。

旅に出る

遠くへ行きたかった。仕事と生活を淡々と繰り返す毎日に、変化のない日々に嫌気がさしたからだ。こうして僕は久々に非日常へと身を投じた。

浜松は良いところだった。鰻も牡蠣も美味いし、浜名湖は大きかった。とても1日じゃ回りきれなかったが、1日掛けても回りきれな場所が日本には、世界には山ほどあるという事実が、この日は嬉しかった。初めての土地で方向感覚が分からなくなって、目的地と違う方向に向かう事が、何気ない非日常の中のワンシーンが楽しくて堪らなかった。

沼津も相変わらず良いところだった。かれこれ5回目…かな。そろそろ見る場所が無くなってしまいそうだけど、何だかんだ沼津に行って、美味しいものを食べて、ここでラブライブ!サンシャイン!!の音楽を聞くだけで、僕は満足出来てしまう。ここは彼女達の物語が紡がれた地だ。僕にとってはそれだけで十分なんだ。

旅は良い。世界の広さを再認識できる。唯一の欠点は、顔と腕がめちゃくちゃ日焼けしてしまう事くらいだろう。次はどこへ行こう、北陸か、東北か、はたまた四国でもいい。

 

f:id:kiui_4:20200905201753j:imagef:id:kiui_4:20200905201801j:imagef:id:kiui_4:20200905201748j:imagef:id:kiui_4:20200905201725j:imagef:id:kiui_4:20200905201713j:imagef:id:kiui_4:20200905201722j:image
f:id:kiui_4:20200905201807j:imagef:id:kiui_4:20200905201716j:image
f:id:kiui_4:20200905201741j:imagef:id:kiui_4:20200905201733j:image
f:id:kiui_4:20200905201730j:imagef:id:kiui_4:20200905201815j:image
f:id:kiui_4:20200905201744j:imagef:id:kiui_4:20200905201804j:image
f:id:kiui_4:20200905201737j:imagef:id:kiui_4:20200905201758j:image
f:id:kiui_4:20200905201727j:imagef:id:kiui_4:20200905201719j:image

8/22 生きる理由

最近、割と真剣に何の為に生きてるんだろうなと考える。そして特に生きる理由も見当たらない。別にだからこそ死のうなんて思わないけど、いざ「明日人類全員死ぬんで!」ってなった時に、他人と比べると後悔することは少ないんじゃないかと思う。むしろ自分より幸せな奴が巻き込まれるなんてラッキー!と嬉々とする可能性もある。

仕事はつまらないし。まぁこれは仕事内容もそうだし、昼休みに何食べようかと考える楽しみだったり、同期や仲良い先輩に会えないのもあって割とつらい。(こんな人間なので、何か用事が無いと連絡できない質なので)まぁ在宅勤務は良いっちゃ良いんだけど、この辺が本当にデメリットだなと感じる。

Aqoursのライブは中止になってしまったし。風呂屋とか映画館とかが営業をしている中で、何でライブだけって気持ちが無い訳じゃないけど、まぁ規模が規模だからしゃーないな...みたいな感じ。オンラインで見れるだけありがたい。

最近の楽しみ...何だろう。風呂屋、明日はメンズエステに行ってみようと考えてる。楽しみ。そう言えば、でっかいモニターを買った円盤を見る環境が整いすぎて、ノーパソで仕事しながらずっとライブの円盤見てる。最高過ぎてAqoursの持ってないライブ円盤全部買っちゃおうかなと思ってる。財布の紐はガバガバになってる、もう俺には何も守るものが無い。

財布ガバガバついでに、風呂も程々にして、多種多様な業種、場所の風俗店に行ってみようと思う。明日のメンズエステはその第一歩だ。(まぁメンズエステは風俗じゃないんですけど)風俗狂いも見方を変えたら趣味の一つだし、極めたら極めたでフォロワーの役に立てそう。ネットのレビューよりフォロワーの実体験とはよく言いますしね。個々のフォロワーに適したお店を紹介できるようになるまで3年くらいかかりそう。最近口を開けば風呂の話しかしてない気がするけど、気のせいです、多分。

最悪な話

良い1日の終わりには、最悪なブログを書くに限る。

ソープに行って参りました。自粛期間で中途半端にお金が貯まってしまい、またお金を貯めておく理由も無くなってしまったので、こう、躊躇の気持ちが無くなってきています。最近ちょっと危機感すら感じてますね。ソープに行って虚しい気持ちになれる人に羨ましさすら感じます。僕は「最高~~~!」って気持ちにしかならないので。もうダメだ。

今日は初めてのお店に行きました。一応、行き付け(?)のソープがあるのですが、行き慣れてしまいスリルを感じる事が出来なくなったし、もっと広い視野を持って色んなソープに行ってみるべきだなと思ったので、今日はちょっと冒険しました。

結論から言うと…めっちゃ良かったンゴぽよの翁w 学園を模した妹系のソープでした。きうは妹系の女の子が大好き。待合室には学校で使ってたような机が置いてあり、内装はとても凝ってましたね。忘れちゃいけないのが、カウンセリングシートと呼ばれる物で、これが本当に良かった。事前に希望のプレイなり嗜好をキャストさんに伝える事が出来るんですよ。美容院かよ…と思いました。「キスはどんなのをご希望でしょうか?」という質問の答えの欄には、フレンチ、普通、ディープ、ねっとり、唾ください、の5つが並びます。まぁ、そりゃ唾くださいに丸付けますよね。「キャストの雰囲気は?」「ウブorエロ」、すまんがエロ一択で。

あと特筆すべき点は、制服がガチってところですね。ちゃちなコスプレ制服じゃないですよアレは。ちゃんとした生地の厚みを感じました。まぁ、きうは女子の制服の事は1mmも知らないんですが。いやでも本格的でしたね。しかも部屋には机までありますからね。凄い拘りです。あっ、因みに女の子はめっちゃかわいくて大満足でした。最高。しかも名前が「かすみちゃん」とかいうも良さポイントあります。

ソープに行く時に緊張感を感じなくなったら、お店の替え時、とはよく言ったものですが、本当にその通りですね。まぁこの言葉は僕が考えたんですけど。人間やっぱり自分にとって新しい物を定期的に摂取しなければなと思いました。この尽きぬ探究心は何処へ向かっていくのやら…。

気になる人が居たらお店とか全然教えるので聞いて下さいね。てか、フォロワーなり友達を連行してみたいという欲が出てきた。1人じゃ怖くてソープに入れないそこのあなた、僕が付き添いましょう。そう、こうして時代は、「軽率に飲酒」から…「軽率にSOAP」へ…。

人を愛するという事

アイドルや声優(以下、アイドル&声優という意味で「アイドル」という言葉を用いています。)を好きになる行為は、とても自由だ。好きになりたい時に好きになって、消費し切れない程のコンテンツをマイペースに消費して、飽きたら離れて、また興味が出たら戻ってくる。誰も咎めるものは居ないし、好きになる事に責任を負う必要は無い。一見聞こえの悪い、誠実さの欠いた行動にも見えるが、これらの行為が許されているのは、アイドルの大きな魅力だと私は考えている。

また、自分の注ぐ愛情が(よっぽど変な事をしない限り)、それがどんなに重い感情であろうと、無条件で受け入れられるのも、アイドルの魅力なのだろう。ありったけの愛情をぶつけても壊れないサンドバッグに、僕はお金を使う。

自分が全力で声優を追いかけていた頃からこの考えを持っていた訳ではないが、少なくとも今の自分の価値観はここに書いたようなものだ。自覚がある。

 

…どうやら、僕の持つ愛情は一般的には「重い」方に分類されるらしい。まぁ確かに昔からその兆候はあった。いつだって、1つのアニメ、1人のアイドルに短期間で深く入り込んでいた。行き場のない愛情を、時にはインターネットの海に放ち、時にはオタクと喋りながら酒と一緒に飲み込んだ。

 

初めてアイドル以外の人間を好きになった。当たり前だが、アイドルを推すのとは訳が違う。そんな事は分かっていた。先述の通り、アイドルを好きになるのは自由だ。しかし、一般的に人を好きになるのは自由なのだろうか。私は No だと思う。勿論、何もかもが許さていない訳では無いが、不誠実な態度や中途半端な覚悟は相手を振り回してしまう。これは良くない。自他がアイドルを無責任に好きになる事に対して、一抹の罪悪感や気持ち悪さを抱いてきた僕は、必要以上に好きになる事、好きでいる事に責任を感じていたし、なんなら愛想尽かされるまでは、ずっと好きでいる覚悟もしていた(と思う)。明らかに重たいと感じるが、僕はこういう態度しか取れなかった。

 

別れてから数日経って、自分のダメだったところが次から次へと思い付く。恋は盲目とよく言うが、本当に何もかも見えていなかった。次があれば、もっと上手くやりたい。

彼女と別れました。

忘れたいけど、忘れたくないから、書く。

付き合う前、色んな人に恋愛相談をする度に「今が一番楽しい時期だね」と言われたのだが、当時の僕は「そんな訳ねぇだろ!!!!」と思っていた。だって好きな人と付き合って楽しくない訳ないじゃん。この言葉の正しさを実感する事になるとは思わなかった。

 めちゃくちゃ好きだった。でも相手の気持ちは変わっちゃうから仕方ない。こう、恋人の距離になれてない感じはちょっと前からあった。僕も僕でやっぱりそれは辛くて、多分このまま続いてもお互いに幸せになれなかったのだと思う。昨日あそこで僕が気持ちを打ち明けなかったら、このなぁなぁの関係がまた1ヶ月、2ヶ月と続いていたのかもしれない。それだったら僕の傷口が浅いうちに別れられて良かったと思う。ショックだったけど、ちゃんと面と向かって向こうが正直な気持ちを伝えてくれたのは、ありがたかった。5ヶ月弱の短い間だったけど、僕にとってはこれが初めてのちゃんとした恋だったし、簡単に忘れる事は出来なさそう。

手元に残ったのは、大事にし過ぎて1回も使ってない誕プレで貰ったマグカップと、今度しようねって言って買った大量の手持ち花火。あとデートで撮った写真。見ると思い出しちゃうから消したいけど、消したらもう一生この写真が目に入ることは無いんだなと思うと、消すのを躊躇ってしまう。

僕にも悪いところはあったのだと思う。この5ヶ月で2人の関係はそれほど進展しなかった。コロちゃんの影響で付き合い始めて2ヶ月目に全く会えない状況になってしまったのは、これはもう運が悪かったとしか言えないけど、ラブラブだった時期にもっと積極的になれてれば、今と違った未来があったのかなと思ったりする。

流石に昨日は死ぬほど辛かったけど、何だかこう、予兆みたいなものは感じ取っていたし、無意識のうちに心が別れの準備してたのか、今は普通に生きてられる。ただ今でも頭の片隅であの子の名前が浮かんだり消えたりしてるし、その度に辛くなるから、これだけは早めに無くなってほしいな。

またオタク家業に没頭出来れば良いんだけど、それも厳しそうだから、しばらく休憩したら新しい出会いを探しに行きたいなと思ってる。さぁどうなるかなぁ。いい男になって、将来、あの子に僕を振ったことを後悔させたい。

今日の頑張り

・今日の頑張り見て

SIGNATEの練習問題をやってたら一日経ってた。下のリンクから見れる。

【練習問題】民泊サービスの宿泊価格予測 | SIGNATE - Data Science Competition

1. MINPAKU.py

データの確認やクレンジング(欠損値の保管や、データのダミー変数化)、変数の返還方針の決定、変換したデータの吐き出し、変数同士の相関をヒートマップで見てる。

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np

# CSV の読み込み
data = pd.read_csv('C:\\work\\SIGNATE\\TRAIN_MINPAKU\\train.csv')

# 欠損地が何個あるか確認
# print(data.isnull().sum())
'''''
・欠損のあるデータと補完の仕方
bathrooms:風呂の数 平均
bedrooms:ベッドルーム数  平均
beds:ベッド数   平均
first_review:最初のレビュー日 x
host_has_profile_pic: ホストの写真があるかどうか    f埋め
host_identity_verified:ホストの身元確認が取れているか  f埋め
host_response_rate:ホストの返信率 平均
host_since:ホストの登録日 2020/1/1
last_review:最後のレビュー日 2020/1/1
neighbourhood:近隣情報 x
review_scores_rating:レビュースコア  平均
thumbnail_url:サムネイル画像リンク x
zipcode:郵便番号 x

・特徴量の選択、加工
1. 削除カラム
id ,description ,name ,neiborhood , thumbnail_url ,zipcode
latitude ,longitude

2. 加工カラム
amenities ⇒ 文字データからアメニティの個数に加工、その後amenities drop
bed_type ⇒ ダミー変数へ加工しdrop
cancellation_policy ⇒ ダミー変数へ加工しdrop
city ⇒ ダミー変数へ加工しdrop
cleaning_fee ⇒ダミー変数へ加工しdrop

last_review - host_since ⇒ 営業日数として扱う
その後 first_review,last_review,host_since drop

host_has_profile_pic ⇒ダミー変数へ加工しdrop
host_identity_verified ⇒ダミー変数へ加工しdrop
instant_bookable ⇒ダミー変数にしてdrop
property_type ⇒ダミー変数にしてdrop
room_type ⇒ ダミー変数にしてdrop

'''
# 欠損値を f で置換
data = data.fillna({'host_has_profile_pic':'f' ,
'host_identity_verified':'f' })
# ホストからの返信率は文字置換して数字型へ
data['host_response_rate'] = data['host_response_rate'].str.replace('%','')
data['host_response_rate'] = data['host_response_rate'].astype(float)
# 欠損値を 平均値 で置換
data = data.fillna({'bathrooms':data['bathrooms'].mean()
,'bedrooms':data['bedrooms'].mean()
,'beds':data['beds'].mean()
,'host_response_rate':data['host_response_rate'].mean()
,'review_scores_rating':data['review_scores_rating'].mean()})

# last_review - host_since を計算
# 日付のデータを - で分割
df_last = data['last_review'].str.split('-',expand=True)
df_since = data['host_since'].str.split('-',expand=True)
# 欠損部分を平均で置換
df_last = df_last.fillna(df_last.astype(float).mean())
df_since = df_since.fillna(df_since.astype(float).mean())
# period を営業している期間の長さとして定義
data = data.assign(period=365*(df_last[0].astype(float)-df_since[0].astype(float))
+ 30*(df_last[1].astype(float)-df_since[1].astype(float))
+ (df_last[2].astype(float)-df_since[2].astype(float)) )
# アメニティの文字データをアメニティの個数データに変換
df_amenities = data['amenities'].str.split(',',expand=True)
data = data.assign(amenities=len(df_amenities.columns) - df_amenities.isnull().sum(axis=1))
# 文字型の変数をダミー変数へ
data = pd.get_dummies(data,drop_first=True, columns=['bed_type','cancellation_policy','city','cleaning_fee'
,'host_has_profile_pic','host_identity_verified','instant_bookable','room_type'])
# 不要なカラムをdrop
data = data.drop(['property_type','last_review','host_since','id','description' , 'first_review','name', 'neighbourhood', 'thumbnail_url' ,'zipcode','latitude' ,'longitude'] ,axis=1)
# 全て1のカラムを追加
data = data.assign(seppen=1)

# 欠損地があるか再確認
# print(data.isnull().sum())

data.to_csv('train_trance.csv')
# ---------------------- 変換ここまで ------------------------------------------------
# ---------------------- 可視化 ------------------------------------------------------
# ダミー変数を除く変数でヒートマップを描いてみる
cols = ['accommodates','amenities','bathrooms','bedrooms','beds','host_response_rate',
'number_of_reviews','review_scores_rating','y','period']
cm = np.corrcoef(data[cols].values.T)
heat_map = sns.heatmap(cm
,cbar=True
,annot=True
,square=True
,fmt='.2f'
,yticklabels=cols
,xticklabels=cols)
plt.tight_layout()
plt.show()

>>出力

f:id:kiui_4:20200711182357p:plain

ヒートマップ

 

2. MINPAKU_LinerRegiression.py

回帰に使う変数や関数をクラスを定義して、線形単回帰と重回帰でパラメータを推定。テストデータで平均偏差を求めて、モデルの評価としてる。最後にSIGNATEのモデル評価用のデータを加工して、予測値を算出してcsvに吐いてる

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt

# 加工したcsv を読み込み
df = pd.read_csv('train_trance.csv')

# ----------------------- 回帰の為のクラスを定義 ----------------------
class liner_Regression(object):
# 学習率とパラメータの更新回数を定義
def __init__(self,eta=0.00000005 ,n_iter=5000):
self.eta = eta
self.n_iter = n_iter

# パラメータを推定する fit メソッドを定義
def fit(self,X,y):
# パラメータ w を初期化
self.w = np.random.random(len(X.columns))
# 更新規則に則ってパラメータを更新
for i in range(self.n_iter):
# 推定値と実測値の誤差を計算
self.error = y - self.predict(X)
# j 番目のパラメータを推定
for j in range(len(X.columns)):
self.w[j] += self.eta * np.dot(X.iloc[:,j], self.error)
return self
# 入力に対して予測値を計算する関数を定義
def predict(self, X):
return np.dot(X, self.w)

# 平均2乗誤差を求める関数を定義
def error_ave_test(self,X,y):
self.errors = y - self.predict(X)
return np.sqrt(0.5 * (self.errors*self.errors).sum()/len(X))
# ----------------------- クラスの定義ここまで ------------------------------------------
# 学習データとテストデータへ分割
df_train, df_test = train_test_split(df,test_size=0.4)

# ----------------------------------------- 単回帰モデルの実装 ---------------------------------------
# 単回帰なので accommodates を説明変数にし、切片を求めるためにseppen を抽出
data_train = df_train[['accommodates','seppen']]
# 目的変数に y を設定
target_train = df_train['y']

# 回帰クラスをインスタンス
linerReg = liner_Regression()
# fit メソッドを呼び出して、学習データにfitするパラメータを推定。
linerReg.fit(data_train,target_train)

# モデルの性能を評価
error = linerReg.error_ave_test(data_train,target_train)
print('単回帰のトレーニン2乗誤差:',error)

# テストデータで2乗誤差を推定
data_test = df_test[['accommodates','seppen']]
target_test = df_test['y']

test_error = linerReg.error_ave_test(data_test,target_test)
print('単回帰のテスト2乗誤差   :',test_error)

# ------------------------------ 重回帰モデルの推定 ----------------------------------------------------
# カラムを指定して説明変数を用意
colmuns = ['accommodates','amenities','bathrooms','bedrooms','beds','bed_type_Couch','bed_type_Futon','bed_type_Pull-out Sofa','bed_type_Real Bed','cancellation_policy_moderate','cancellation_policy_strict','cancellation_policy_super_strict_30','cancellation_policy_super_strict_60','city_Chicago','city_DC','city_LA','city_NYC','city_SF','cleaning_fee_t','host_has_profile_pic_t','host_identity_verified_t','instant_bookable_t','room_type_Private room','room_type_Shared room','seppen']
data_train = df_train[colmuns]
# 目的変数に y を設定
target_train = df_train['y']

# 重回帰クラスをインスタンス
Multiple_regression = liner_Regression()
# fit メソッドを呼び出して、学習データにfitするパラメータを推定。
Multiple_regression.fit(data_train,target_train)
# モデルの性能を評価
error = Multiple_regression.error_ave_test(data_train,target_train)
print('重回帰のトレーニン2乗誤差:',error)

# テストデータで2乗誤差を推定
data_test = df_test[colmuns]
target_test = df_test['y']

test_error = Multiple_regression.error_ave_test(data_test,target_test)
print('重回帰のテスト2乗誤差   :',test_error)

# ----------------------- 予測した様子を可視化 ----------------------------------------------
plt.scatter(target_test, Multiple_regression.predict(data_test))
plt.xlabel('correct')
plt.ylabel('predict')
plt.show()

# ------------------------------- テストデータから予測値を計算 -----------------------------------------------
# CSV の読み込み
data = pd.read_csv('C:\\work\\SIGNATE\\TRAIN_MINPAKU\\test.csv')

# 欠損値を f で置換
data = data.fillna({'host_has_profile_pic':'f' ,
'host_identity_verified':'f' })
# ホストからの返信率は文字置換して数字型へ
data['host_response_rate'] = data['host_response_rate'].str.replace('%','')
data['host_response_rate'] = data['host_response_rate'].astype(float)
# 欠損値を 平均値 で置換
data = data.fillna({'bathrooms':data['bathrooms'].mean()
,'bedrooms':data['bedrooms'].mean()
,'beds':data['beds'].mean()
,'host_response_rate':data['host_response_rate'].mean()
,'review_scores_rating':data['review_scores_rating'].mean()})

# last_review - host_since を計算
# 日付のデータを - で分割
df_last = data['last_review'].str.split('-',expand=True)
df_since = data['host_since'].str.split('-',expand=True)
# 欠損部分を平均で置換
df_last = df_last.fillna(df_last.astype(float).mean())
df_since = df_since.fillna(df_since.astype(float).mean())
# period を営業している期間の長さとして定義
data = data.assign(period=365*(df_last[0].astype(float)-df_since[0].astype(float))
+ 30*(df_last[1].astype(float)-df_since[1].astype(float))
+ (df_last[2].astype(float)-df_since[2].astype(float)) )
# アメニティの文字データをアメニティの個数データに変換
df_amenities = data['amenities'].str.split(',',expand=True)
data = data.assign(amenities=len(df_amenities.columns) - df_amenities.isnull().sum(axis=1))
# 文字型の変数をダミー変数へ
data = pd.get_dummies(data,drop_first=True, columns=['bed_type','cancellation_policy','city','cleaning_fee'
,'host_has_profile_pic','host_identity_verified','instant_bookable','property_type','room_type'])
# 不要なカラムをdrop
data = data.drop(['last_review','host_since','id','description' , 'first_review','name', 'neighbourhood', 'thumbnail_url' ,'zipcode','latitude' ,'longitude'] ,axis=1)
# 全て1のカラムを追加
data = data.assign(seppen=1)

# データから予測値を計算
data = data[colmuns]
predicts = Multiple_regression.predict(data)
predicts = pd.DataFrame(predicts)
predicts.to_csv('predicts.csv',header=None)


# 参考 -----------------------正規方程式を使った回帰パラメータの推定 ------------------------------
def normal_equation(X,y):
param = np.linalg.pinv(X.T.dot(X)).dot(X.T).dot(y)
return param
W = normal_equation(data_train,target_train)

# --------------------------------------- ここまで ----------------------------------------------------

>>出力

単回帰のトレーニング2乗誤差: 101.35950150166111
単回帰のテスト2乗誤差   : 101.34383018796446
重回帰のトレーニング2乗誤差: 92.66598989721335
重回帰のテスト2乗誤差   : 92.4839200158771

プロセスは終了コード 0 で完了しました

まぁ重回帰の方が予測性能が良い、過学習してる様子も見られないし、線形回帰の限界はこの辺りにありそう。まぁデータから有益な特徴量を作れれば話は別なんだけど、どうやって作るんだろ...。今度は非線形の回帰も勉強してみるか...。因みに自分でクラスを定義したのは初めてだったんだけど、使ってみると便利さが分かるね...。

 

3. Nural_network_regression.py

線形回帰の限界をみたので、気になっているニューラルネットワーク回帰に手を出してみた。中身はブラックボックスだけど、やっぱり予測の精度は重回帰より全然よかった。ただ使う分にはこれで問題ないのだけど、やっぱり使うからには中身で何やってるか理解しないと何か気持ち悪いな...。何も分かってなくても回帰より良い結果が得られちゃうの、ちょっと怖い。

import numpy as np
import pandas as pd
from sklearn.neural_network import MLPRegressor
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt

# 加工したcsv を読み込み
df = pd.read_csv('train_trance.csv')

# 学習データとテストデータへ分割
df_train, df_test = train_test_split(df,test_size=0.4)

colmuns = ['accommodates','amenities','bathrooms','bedrooms','beds','bed_type_Couch','bed_type_Futon','bed_type_Pull-out Sofa','bed_type_Real Bed','cancellation_policy_moderate','cancellation_policy_strict','cancellation_policy_super_strict_30','cancellation_policy_super_strict_60','city_Chicago','city_DC','city_LA','city_NYC','city_SF','cleaning_fee_t','host_has_profile_pic_t','host_identity_verified_t','instant_bookable_t','room_type_Private room','room_type_Shared room','seppen']
data_train = df_train[colmuns]
# 目的変数に y を設定
target_train = df_train['y']

# ニューラル回帰をインスタンス
mlp = MLPRegressor(hidden_layer_sizes=(100,), max_iter=500)
mlp.fit(data_train, target_train)

# テストデータの生成
data_test = df_test[colmuns]
target_test = df_test['y']

# predict関数で予測値を計算
pred = mlp.predict(data_test)
# 平均2乗誤差を計算
errors = np.sqrt(0.5*((target_test - pred)*(target_test - pred)).sum()/len(pred))
print('ニューラルネットワーク回帰の2乗誤差:',errors)

plt.scatter(target_test, pred)
plt.xlabel('correct')
plt.ylabel('predict')
# plt.show()

# -------------------------- テストデータに対して予測値を計算 -----------------------------------
# CSV の読み込み
data = pd.read_csv('C:\\work\\SIGNATE\\TRAIN_MINPAKU\\test.csv')

# 欠損値を f で置換
data = data.fillna({'host_has_profile_pic':'f' ,
'host_identity_verified':'f' })
# ホストからの返信率は文字置換して数字型へ
data['host_response_rate'] = data['host_response_rate'].str.replace('%','')
data['host_response_rate'] = data['host_response_rate'].astype(float)
# 欠損値を 平均値 で置換
data = data.fillna({'bathrooms':data['bathrooms'].mean()
,'bedrooms':data['bedrooms'].mean()
,'beds':data['beds'].mean()
,'host_response_rate':data['host_response_rate'].mean()
,'review_scores_rating':data['review_scores_rating'].mean()})

# last_review - host_since を計算
# 日付のデータを - で分割
df_last = data['last_review'].str.split('-',expand=True)
df_since = data['host_since'].str.split('-',expand=True)
# 欠損部分を平均で置換
df_last = df_last.fillna(df_last.astype(float).mean())
df_since = df_since.fillna(df_since.astype(float).mean())
# period を営業している期間の長さとして定義
data = data.assign(period=365*(df_last[0].astype(float)-df_since[0].astype(float))
+ 30*(df_last[1].astype(float)-df_since[1].astype(float))
+ (df_last[2].astype(float)-df_since[2].astype(float)) )
# アメニティの文字データをアメニティの個数データに変換
df_amenities = data['amenities'].str.split(',',expand=True)
data = data.assign(amenities=len(df_amenities.columns) - df_amenities.isnull().sum(axis=1))
# 文字型の変数をダミー変数へ
data = pd.get_dummies(data,drop_first=True, columns=['bed_type','cancellation_policy','city','cleaning_fee'
,'host_has_profile_pic','host_identity_verified','instant_bookable','property_type','room_type'])
# 不要なカラムをdrop
data = data.drop(['last_review','host_since','id','description' , 'first_review','name', 'neighbourhood', 'thumbnail_url' ,'zipcode','latitude' ,'longitude'] ,axis=1)
# 全て1のカラムを追加
data = data.assign(seppen=1)

colmuns = ['accommodates','amenities','bathrooms','bedrooms','beds','bed_type_Couch','bed_type_Futon','bed_type_Pull-out Sofa','bed_type_Real Bed','cancellation_policy_moderate','cancellation_policy_strict','cancellation_policy_super_strict_30','cancellation_policy_super_strict_60','city_Chicago','city_DC','city_LA','city_NYC','city_SF','cleaning_fee_t','host_has_profile_pic_t','host_identity_verified_t','instant_bookable_t','room_type_Private room','room_type_Shared room','seppen']
data = data[colmuns]

# predict関数で予測値を計算してcsvに吐き出す
pred = mlp.predict(data)
predicts = pd.DataFrame(pred)
predicts.to_csv('NN_predicts.csv',header=None)

>>出力

ConvergenceWarning: Stochastic Optimizer: Maximum iterations (500) reached and the optimization hasn't converged yet.
% self.max_iter, ConvergenceWarning)
ニューラルネットワーク回帰の2乗誤差: 86.69826189432175

ちょっとエラーは言えるけど原因分から無し、でも結果は出てるから無視...。

以上。

 

7月頭のお話

いつも通り日記付けようと思ったらブログ開設3周年ですと言われて、そういえば始めたのは7月の頭だったなと思い出してた。このブログについてそんな語ることもないので、これからも読んでくれたら嬉しいなとだけ言っておきます。まぁ別に読んでくれなくても貴方が生きてくれてるだけできうは嬉しいよ。

f:id:kiui_4:20200705193146p:image

 

・日記

実は友達とスポッチャに行こうという話があったのだけど、昨今の情勢を見て延期になってしまった。しょうがない事ではあるけど、割とショック...。スポッチャ行くなんて高校生以来だから、結構楽しみにしてた...。という訳で、週末は半ば虚無みたいな生活をしてました。

土曜の夜は暇すぎて話題のチェーンソーマンとかいう漫画を全巻買って読んじゃいましたね。おかげで、まぁ完全な虚無にはならなかったかなぁという感じです。チェーンソーマンは各所で面白いと騒がれていたし、実際に身近な人にも勧められたりして、面白いんだろうなと思っていましたが、まぁ読んでみると想像通り面白かったです。ですが、途中からは面白いと分かっている漫画を面白いと確認する作業のようになってしまって、意外と僕の心の奥底には響かなかったかなぁ...というのが正直なところです。多分、もっと違う出会い方をしたら、心を抉られるような作品として自分の中に幾分か残ったかもしれません。昔からそうですが、人から面と向かって勧められた作品は大体中途半端な消費に終わっちゃいますね何故か。自分の興味のままに触れる作品の方が、面白いか面白くないかは置いといて、有意義な消費になっている気がします。

今日は劇場版サンシャインを見ました。2ヶ月に1回くらいのペースで見たくなる作品。そして見る度にボロボロに泣く。泣くのは健康に良いらしいので、できれば定期的に泣いておきたい。春クールもアニメを見て面白いねぇ~とは思うのだけど、なんだかんだ言っても自分の中に残るような作品にはならなくて、まぁそんな何でもかんでも心に残りまくっても嫌だけど。感情のストレッチは大事だから、沢山の作品を見ていっぱい感動できる方が僕は良いなと思っているのだけど、出来ないものはできないわな。一先ず、まだ僕は劇場版ラブライブを見たり、激情版サンシャインを見て顔をぐちゃぐちゃに出来るので、それが出来なくなってから色々考えようと思う。

そういえば、6月末で僕が1年間お世話になった会社の先輩が退職してしまったのだけど、退職の挨拶のメールが凄く良くて泣きそうになってしまった。思い出話をするのは反則だと思う。そのメールに触発されてLINEでご挨拶の連絡をいれたら、また嬉しい返事が返ってきて、本当に素敵な人だなぁと思った。久々に熱い気持ちになった。こう、感情的になれる機会がもっとあればいいのになと思う。