ITエンジニアのブログ

IT企業でエンジニアやってる人間の日常について

漫画「四月は君の嘘」を読んで

元いた会社の同期などに勧められて、「四月は君の嘘」を読みました。

母の死をきっかけにピアノが弾けなくなってしまった主人公の有馬公生が、他クラスの同級生であるヴァイオリニストの宮園かをりや、他の人物との出会いによって成長、変化していく物語です。

最終の11巻まで読みました。


ネタバレになるためあまり多くは語りません。

なんというか、とても切ない物語でした。読み終わった後の余韻がとても長く続いていて、読んでよかったと思える作品でした。

音楽への関心があれば話に入りやすいとは思いますが、話のメインは音楽というより、人間関係や成長を描いたもので、青春マンガっぽいです。

メッセージ性のあるセリフがいくつか出てきて、とても印象に残っています。


iMac 2020 使用感

iMac 27inch 5K Late 2014 (以下 Late 2014) をメインマシンとして使っていましたが、先月 iMac 27inch 2020 (以下 iMac 2020) を購入しました。使っていて1ヶ月程度経ったため、使用感を書いてみたいと思います。

f:id:tfull:20200913113948j:plain
iMac 27 inch 2020

なぜ iMac 2020 を買ったか

Late 2014 の HDD ストレージが不安だった

Late 2014 のメインマシンは、ストレージに Fusion Drive 3 TB を選択していました。殆どがハードディスクとなっているわけですが、以前7年ものの Mac Book Pro の HDD が壊れて起動しなくなったことから、ハードディスクの老朽化、消耗に関して凄く不安に思いながら使っていました。

High Sierra からアップグレードできずにいた

Late 2014 には音楽ソフト Cubase やそれに付随するライセンスソフトウェアが入っており、バージョン的に Catalina に対応していないらしいこと、また、アップグレードの際に何かが動かなくならないという保証もなかったため、 High Sierra から Catalina に以降を躊躇していました。 Catalina では、 Docker や Side Car などの私がよく使う機能などが使えるため、アップグレードしたいという思いもあり、板挟みの状態でした。 PC が2台あれば、危険をあまり冒さずに適宜アップグレードできるのですが。

Intel 最後となる iMac かもしれない

Apple Silicon という Apple 社独自のチップが発表され、年内にも発売される可能性があるということで、それを楽しみにしている面もあるのですが、私がよく使っているソフトウェアなどが完全に動作するかというのはわかりません。特に、 Cubase などが最初からうまく動作するかというのは疑問だったため、 InteliMac が最後であれば、今のうちに買っておくべきだと思いました。

以上の要因が重なり、購入という決断をしました。

性能

f:id:tfull:20201013035709p:plain
性能

値段、税込み約62万円。高い。しかし、四六時中向かっているPCですから、こういうところで妥協するわけにはいかないとも思っています。

性能のカスタマイズオプションは、メモリが128GB積めるのと、SSD が8TBまで増やせるのですが、このオプションだけ段違いにコストが掛かります。

メモリは後からでも入れ替えられますし、沢山データを管理したいのであれば外付けのストレージを活用するべきだと思っているため、このあたりは選びませんでした。妥協しないのと不必要なものを購入するのは違うと思っています。

あと、あまり詳しくないですが、メモリを大きくするとその分だけ使ってしまい、スリープ時にスワップ領域に書き込んでストレージが疲弊すると思ったのもあります。Mac ではメモリは必要な分だけを適切に選ぶという方針にしています。

メモリは最安値の8GBで購入し、自分で入れ替えるということもできるのですが、カーネルパニックを起こしたり、相性が悪くて使い物にならなかったりするリスクを考えて、最初からオプションで64GBを選択しました。メモリを付け足すことでクロック数が落ちるという報告も出ているようです。

使用感

Cubase の起動はあまり変化がなかった

Fusion Drive から SSD にすることで、音楽を作成するときに立ち上げる Cubase の起動時間が劇的に短くなることを期待したのですが、あまり大きな変化は無かったように感じます。起動が遅いのはアプリ側の問題かもしれません。

しばらく白線がチラつく不具合があった

一時期話題になった、白線がチラつく不具合が、私のマシンでも起こりました。 (iMac 2020 Graphical Glitch で検索)

GPU が 5700XT のもののみで起こることを知っていて、購入時にスペックを落とすか迷っていたのですが、あまり日本で不具合の話を聞いておらず、 Apple Store の店員さんとも相談して大丈夫だと思ったので、性能は妥協せず購入しました。

しかし、セットアップの段階で白線がチラつき、冷や汗をかきながら使いはじめましたが、やはり通常の使用時にも現れており、その度にドキッとする感じでした。

これが結構ストレスになっていて、ソフトウェアアップデートで解決される可能性が高いということで、アップデートを待っていました。

10.15.7 にアップデートすることで解決しました。今はストレスなく使えています。

Catalina は良い

MacBook Pro 16 inch 2019 で体感済みですが、やはり Catalina は便利です。 Side Car, Docker など。

USB Type-C が良い

まだ本格運用はしていませんが、 USB Type-C があると便利ですね。 Late 2014 の Mini Display Port はもはやあまり使い物にならないので、この変化は大きいです。

所々でスペックの高さを感じる

たまに動画の編集、書き出しをやっている程度で、あまり重たい動作はまださせていませんが、軽快に動作している感覚があります。

まだ取りかかっていないものの、自然言語処理などをさせる場合には最大限の動作をすることになるだろうと思っています。

変なノイズについて

Late 2014 では、 ChromeTwitter で大きな画像を開いたときや、画面ロックとしてスクリーンを消したときに、「チッチッチッ」というノイズが発生していました。ゲームを起動してみるととても大きく速い音になるため、おそらく GPU の問題だろうと思っており、これがとても気になっていました。iMac 2020 では、それが落ち着きました。スクリーンを消したときだけ少し音がしないでもないですが、前よりは大幅に改善しています。

買ってよかった

Docker は便利です。プログラムを沢山書く人間にとっては、環境を汚さずいろいろできます。最近は数式を含む文章を LaTeX で記述していますが、 tex 系はわりと環境を汚すため、それを Docker によって避けられています。

Side Car は便利です。 iPad Pro 2020 を持っているため、いい感じに連携できます。 Clip Studio Paint なども捗りますね。

iPad Pro でノートに描いた絵や図などが iMac 側でもノートアプリですぐに反映されるため、ちょっとしたデータのやり取りがかなり便利です。

Cubase はアップグレードして、最新のものを使えています。結構格好良くなっている。

Late 2014 で使っていたオーディオインターフェイスが、 Catalina で使えなくなっていました。やむを得ず YAMAHA AG03 を購入、予想外の出費。

問題点

見た目の変化が無いため、ベゼルが太いままです。もう少し洗練されていれば机もスッキリするのに。

Late 2014 はまだ使えるけどどうしよう。





iMac を検討している人の参考になれば。

最近知った・気がついたこと(国語、数学)

【国語】「お」と「を」は発音が違う。

たまに Twitter で議論が流れて来たりするため、知識としては知っていました。しかし、「を」を意識して発音を変えることはしていませんでした。

しかし、今やっているゲームで声優さんが発音しているのを何気なしに聞いたとき、「を」の発音が明らかに「お」と異なっているのに気づいたのです。(「うぉ」と「お」の中間のような感じ)

その発音をあまりに綺麗に感じたため、少し発音について意識するようになりました。

特に意識していなかったような箇所から新しい発見を得られるのは楽しいですね。

【数学】同値記号は、単なる式変形で乱用しないほうが良い。

2倍角の公式より、

\displaystyle \cos\frac{\pi}{4} = 1 - 2\sin^2\frac{\pi}{8}
が成り立ちますが、この式を整理して、次の行に

\displaystyle \iff \sin^2\frac{\pi}{8} = \frac{2 - \sqrt{2}}{4}
と書いたとき、同値記号⇔を使うことに違和感を感じました。

今まで、両辺を平方したり、0の可能性のある値で除算するときなどには気をつけて、式変形のときに同値記号をよく使っていました。前から後を主張したいときに、「ゆえに」の∴のほうが意味合いとしては正しそうでも、ゆえにを乱発するのは不格好であると考えていたためです。

しかし、上の式変形で同値記号を使うのは不自然な気がしました。cos(π/4)も、sin(π/8)も具体的な値であるため、1 + 1 = 2のような式と本質的には変わらないからです。

これが、例えば文字xについての条件を考えている場合ならば、式変形で同値関係を主張するのもわかります。

3x - 1 = 2 \\
\iff \quad x = 1

しかし、次のような表現は、同値記号の両側が恒真であるため数学的に正しいとしても、議論をしているという視点に立てば、何を主張したいのかがわかりません。

1 + 1 = 2 \iff 2^3 = 8

これを考えると、最初の式変形に同値記号を使うのは、間違いではないにせよ違和感があります。

また、同値記号を乱用するデメリットとして、どこかで同値関係が崩れる式を含んでしまえば、主張自体が誤りとなり、試験の答案であれば減点対象になります。よくある例としては、先程あげたような、両辺を2乗したり0の可能性のある値で除算するときなどです。

言われてみれば、試験の答案に間違った主張が含まれれば減点されるのは当然のことなので、無闇に同値記号を使うのは得策ではありません。

たくさん式を書きたい場合、「式を整理すると...」などと記述して、上から順番に式を列挙していけばよいのです。

また、自然言語(日本語、英語など)を上手に使ったり、議論の順序を入れ替えたりすることで、議論が単なる式の羅列になることを避けたほうが良さそうです。

早く気がつけばよかったと思いました。

質問応答システムの実装と考察: BERT for Question Answering を使ってみる

背景

日本語の質問応答システムの実装です。

前回は、機械学習を用いない、基本的な数値演算の組み合わせで、回答を選択するモデルを構築しました。しかし、精度や速度に改良すべき箇所をたくさん残しています。

↓ 前回
質問応答システムの実装と考察:BOWとTFIDFによる検索 - 燻ったエンジニアのブログ

今回は、機械学習手法を用いて、質問応答を試してみました。

BERT と呼ばれる、 Google 社が開発した自然言語処理のための機械学習手法です。

文章の一部の単語を隠し、それを予測する Masked Language Model と、2つの文章が繋がっている(ちょうど前後に位置している)かを予測する Next Sentence Prediction により文章を学習し、分類などの問題を解けるようにするというのが概要です。

言語は問わないため、日本語を学習させて、日本語の質問に答えさせてみます。

準備

私はコーパスとして Wikipedia をよく使っていますが、 BERT でこの規模の文章を学習するのはとても時間がかかり、数週間から数ヶ月ほどになるようです。したがって、自宅のパソコンで学習を行うのは、電気代や機器(特に GPU)の消耗の観点からしても非現実的です。

ですので、公開されている学習済みモデルを取得します。

↓ 参考にしたページ
BERT日本語Pretrainedモデル - KUROHASHI-CHU-MURAWAKI LAB

環境は Python 3.7.6 を使いました。 BERT を使うために、 pip で transformer を入れる必要があります。また、学習済みモデルの形態素解析器と合わせるために、 Juman を使いました。計算にpytorchも使っています。

実験

BERT の事前学習モデルを読み込みます。

bert_qa = BertForQuestionAnswering.from_pretrained("/path/to/model")

質問を用意します。

context = "..."
question = "..."
answer_words = "..."

形態素解析をします。

juman = Juman()

def juman_tokenize(text):
    return [mrph.midasi for mrph in juman.analysis(text).mrph_list()]

context_words = juman_tokenize(context)
question_words = juman_tokenize(question)
answer_words = juman_tokenize(answer)

BERT Tokenizer を用いて解析します。

tokenizer = BertTokenizer.from_pretrained("/path/to/model")

tokenized = tokenizer.encode_plus(
    " ".join(question_words),
    " ".join(context_words),
    max_length = 128,
    pad_to_max_length = True,
    add_special_tokens = True,
)

モデルに与えてみます。

input_ids = tokenized["input_ids"]
attention_mask = tokenized["attention_mask"]
token_type_ids = tokenized["token_type_ids"]

start_scores, end_scores = bert_qa(
    torch.tensor([input_ids]),
    token_type_ids = torch.tensor([token_type_ids])
)

start_scores, end_scores から、スコアの高いものの場所を選択し、その範囲を回答と決定します。
end_scoresの高いものが後ろに来るように、スコアを調節しています。

start_index = int(torch.argmax(start_scores))
score_mask = torch.tensor([-10000] * (start_index + 1) + [0] * (128 - start_index - 1)).reshape(1, 128)
end_index = torch.argmax(end_scores + score_mask)

文字に起こして回答を得ます。

response_tokens_tmp = input_ids[start_index : end_index + 1]
response_tokens = tokenizer.convert_ids_to_tokens(response_tokens_tmp, skip_special_tokens = True)
response = "".join(response_tokens)

response に回答の文字列が格納されます。

結果

質問1

context = "明智光秀は、織田信長を本能寺の変で討った後、山崎の戦いで豊臣秀吉に討ち取られた。"
question = "本能寺の変で織田信長を討ったのは誰。"
answer = "明智光秀"

回答1

、山崎の戦いて豊臣秀吉に討ち

質問2

context = "浅井家当主の長政は、織田家に追い詰められた後、自害した。"
question = "長政は追い詰められたときどうした。"
answer = "自害した。"

回答2

、織

質問3

context = "今日は8月25日です。昨日から今日にかけて関東では雨が降っていましたが、明日は快晴になり、気温は上昇する見込みです。"
question = "明日の天気はどうなる?"
answer = "快晴"

回答3

、明日は快晴になり、気温は上昇する見込み

質問4

context = "このゲームは、定価1000円ですが、7割引となっており300円で購入できます。"
question = "ゲームは何円で買える?"
answer = "300円"

回答4

円て買える?このケー##ムは、定価円て##すか、割引となっており


4つの質問を投げてみました。

結果としては、あまりいい回答を得られないように見られました。3つめ(質問・回答3)だけは良さそうです。

4つめについては、 BERT で tokenize した形跡が残ってしまっているので、コードに間違いがないか要調査です。

考察

以下のようなことがわかります。

  • 回答候補となる文章を与えなければならない。
  • 回答は与えられた文章から抽出してくるため、文章に回答が載っていないと正しく答えられない。
  • 短い文章でもあまり的確に答えられない。
  • 単語でも文章でも回答できる。(ファクトイド、ノンファクトイド両刀)
  • 知識ベースでなくても回答できる。(明日の天気など)

私が目指している質問応答システムとは方向性が違うようですが、参考にできるものもあるかもしれません。特に、 Masked Language Model と Next Sentence Prediction の考え方は取り入れる価値がありそうです。(難しそうですが)

また、 BERT の学習時間が膨大であることを考えると、個人の趣味の範囲で効果的な機械学習モデルを構築、学習、実験するのはかなり難しい、あるいは非現実的ではないかという考えが過ぎり、暗雲が立ち込めてきました。

社会人のコミュニケーション力についてエンジニアが感じたこと

始めに

ソフトウェアエンジニアとして、また社会人として数年の時を過ごし、自分自身が成長したと思うような事柄がいくつかあります。コミュニケーション力はその内の一つです。

コミュニケーション力が必要とはよく言われているものですが、必要と言われたからといってどうしたら良いのか、どうすれば身につくのか分からなかった経験が私にあるので、同様に考えられている方がいらっしゃれば参考になれば良いかなと思います。

あくまで、IT企業で働くエンジニアの場合なので、他の業種の場合は少し変わってくるかもしれませんし、私とは全く異なるような考えを持たれている方もいらっしゃる可能性についてはご理解ください。

本題に至る背景

私の過去、学生時代について話します。
私はとても人見知りする性格で、仲の良い人以外とは色々とお喋りするものの、それ以外の人とは本当に最低限の必要な会話のみをしていました。高校生の時までは級友と同じ教室で長い時間を過ごすため、自分を伝えたり知ってもらう機会も沢山あったので良かったものの、大学生時代はそうもいかず、孤独な気分を味わっている時期がありました。自己評価としても凄くコミュ力の低い人間だと思っていたため、就職活動でそういうのが主に評価されるのであれば凄く不利になるな、嫌だなと思っていました。

実際に就職活動は甚だ苦戦した過程がありましたが、これに関して、私の魅力の無さやコミュニケーション力の不足からくるものだろうと、半ば諦めの気持ちで、考察の材料もないため徹底的に分析をすることもありませんでした。

なんとか採用していただいた会社で数年働きましたが、その社会人経験で体感したこととして、社会人に求められるコミュニケーション力は、大学生の時に欲しかったそれとはかなり性質が違うことに気が付きました。そのことによって、今までよくわからなかった概念の正体がわかり、視界がひらけるような感覚があったのです。

私が考える社会人のコミュニケーション力

社会人のコミュニケーション力とは、大学生でよく言われるそれとは違い、知らない人とすぐに打ち解けたり、飲み会で騒いだり、居酒屋や牛丼屋で「アッ...」とならずに店員さんを気兼ねなく呼ぶスキルではありません。勿論、それらは生活上役に立つし、仕事でも役に立ちうるものでありますが、この話での主要たるものではないでしょう。必要なのは、困っていることを相談したり、そのために誰がどんな情報を握っているのかを常に把握したり、仕事を進める際の情報共有で情報を過不足なく連ねて発信したり、仕事仲間のために自分の持っている情報や知識を伝えたり、といったことを適切に行う力です。これらは、ただ単純に気さくかどうかなどの性格によるものではなく、専門知識の深掘り、あるいはビジネスの対象としているドメイン知識(※1)の理解、あるいは文章の理解力や思考力といったものです。そして、それらは十分に鍛えうるチャンスのあるものに由来します。

上記のようなことを、業務を進めていくにつれて、ああ、こういう意味だったんだと実感するに至りました。あくまで私が体感したことで、正解というものではありませんが、自分自身にはかなり確信を持って腹落ちできました。

専門知識の深掘りによってコミュニケーション力が高まるということについてもう少し掘り下げて説明してみます。ソフトウェアエンジニアの場合、プログラムやシステムを動かしているときに問題に差し掛かった場合、さて相談しようとなったときに、知識が少ない状態だと「なんかエラーが起きました。こう書いてあります。」といった説明だけしかできないかもしれません。しかし、知識や経験がある程度身についた場合、「Aを実現するためにBが必要なので、資料Cに記されている手順を実行したところ、Dというエラーが出ました。Eといった理由でFである可能性が考えられますが、いかがでしょうか。Gを行っても良いですか。」のように、具体的な説明ができるかでしょう。これで、円滑な情報共有が行われ、仕事が停滞せずに進みます。また、いつ相談すべきか、いつこちらから情報提供すべきかといったタイミングに関しても、何となく分かるようになってきます。ドメイン知識でも同じようなことが言えますし、勉強などで鍛えられる文章の理解力や思考力を発揮すれば、キーワードの選定や文章構成が洗練され、一つ一つの文章の精度が底上げされます。

私の場合は、仕事を進める上で数年の時間をかけて自然と身についていったものではありますが、この到達点がわかっていれば、意識的な訓練をすることも可能だと思われます。少なくとも、「ノリよく話そう!」と言われてもすぐに実行するのは難しいかもしれませんが、相手側の脳内で再現ができるように、(上の例では)背景、理由、自分がどうしたか、これからどうしようと思っているのかなどのポイントを押さえて文章に起こす、というのは、思考の訓練ができている人であれば素直にできることではないでしょうか。

私が苦戦した就活の場面でも、同じことが言えたはずです。ハキハキ発声する、円滑に話すといったことは、もちろん良い第一印象を与える上では重要ですが、肝心の話の中身については、例えば自分の強みはこうで、それはどういった経緯で身についたもので、ああいう場面で応用ができて、どういった点で他と差別化ができるのか、のように、初対面の相手がきちんと理解できるように本質的な構成要素を選定し、鍵となる単語を並べ、筋道を立てて伝えれば、良い印象となって残るはずです。魅力が無いのではなく、魅力が相手に伝わっていないだけだったのでしょう。

派生して

コミュニケーション力を身につけた因果関係か、単純に年齢を重ねた結果か、社会人として沢山の人と関わるようになったゆえか、真相はわかりませんが、人に気軽に話せるようになりました。初めて会う人と世間話を交わしたりとか。何かの店で店員さんが近くにいないときも、その場まで歩いていって呼んだりとか。

最後に

私自身もまだまだコミュニケーション力が高いとは言えませんが、社会人経験で気づきを得てとても成長できたと思っております。要は、相手が思考内で状況の再現ができるように、各構成要素を並べて伝える、ということが大事です。仕事以外の場面でも使えるでしょう。コミュニケーション力という得体のしれないものに悩んでいる方は、様々な方の意見を取り入れてみてください。私の一例も参考になると嬉しいです。

補足

※1
ドメイン知識:扱っている対象の知識のこと。例として、ゲーム業界ならゲームの知識、広告業界なら広告やマーケティングなどの知識。

php -S で PDF がブラウザ表示されなかった

PDFをリモートサーバー作成していて、ブラウザで確認しようとして Firefox で開いたのですが、 PDF がファイル保存となってしまい、困惑しました。

原因は、 php -S でサーバーを起動していたのですが、 php が 5.4 でした。

PHP 5.5.5 から .pdf が MIME サポートされており、 php 5.4 では MIME サポートされていなかったため、ブラウザが pdf として解釈できず、とりあえず保存しよう、となっていたということです。


リモートサーバーには Docker をインストールしていたため、

PORT=ポート番号
docker run --rm -v ${PWD}:/usr/local/apache2/htdocs/ -p ${PORT}:80 httpd

httpd を起動することにより解決しました。

Unity:Resources.LoadAllのタイミングで嵌った。

Unityで画像をロードしながら表示させるときに、タイミングの妙によってうまく表示できていませんでした。


1: Instantiate によって生成されるオブジェクトのスクリプト

// class Sub

void Start() {
    this.sprites = Resources.LoadAll<Sprite>("Numbers/");
}

void Method() {
    // ...
    SpriteRenderer renderer = (SpriteRenderer)obj.AddComponent<SpriteRenderer> ();
    renderer.sprite = this.sprites[0];
}


2: インスタンスを作成する側のスクリプト

GameObject instance = Instantiate(obj_x, transform.position, transform.rotation);
instanceGetComponent<Sub>().Method;


2:の方でインスタンスを作ってすぐにメソッドを実行しました。

こうすると1:の方で Start() が終わる前に Method()が実行され、画像がロードできていない不具合が発生します。

Startではなく Awake を使うか、画像を入れる処理を Update() にすべきでした。