ITエンジニアのブログ

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

プログラミング中に詰まったメモ(ブラウザインターフェイス編)

個人で使うアプリケーションのブラウザインターフェイスを作っていたところ、いくつか詰まったのでメモしておきます。

JavaScript の整数値の上限、下限に注意

サーバー側を Python で、クライアント側を jQuery で作っていました。サーバーから大きな整数値をフロントに渡し、さらにそれをいくつかサーバーに送り返すというプログラムを書いていたのですが、なぜか値がおかしくなっておりその後の処理が動かないという状況が起こりました。

JavaScript は整数値を 64bit 浮動小数点数の形式でもっているため、上限がそんなに大きくない値で定まっています。そのことを失念していたため、端数が切り捨てられて違う値になっていました。

なんらかの id など、大きい値の場合は、文字列でやり取りするべきでした。

jQuery で、追加された要素の on click が反応しない

$(".some_class").on("click", function() {
     alert(1);
});

なんらかのイベントで追加される .some_class クラスを持った DOM が生成されるとき、上記の設定では反応がありません。正しくは次のようにする必要があります。

$(document).on("click", ".some_class", function() {
    alert(1);
});

いかに機械学習を使わないかを考えるのも機械学習エンジニアだと思う

今まで、業務として機械学習に触れてきた経験から、色々と思料したので共有します。

機械学習を適用することのデメリット

機械学習を用いると、それ以外では叶わなかった問題の解決などが可能になる場合があります。ですが、機械学習は良いことばかりではありません。特有のデメリットを克服するか、あるいは上回る利点を出す必要があります。

出てきた結果の説得力が無い

出力された分類結果や回帰の値に対して、どうしてそうなったかという理由は付与してくれません。ニューラルネットワークの場合を考えると、ただ内部で数値が変動し、それが出力になるだけです。そしてそれがプロダクトになったとき、それを使用する人に説明する機会でその問題が顕在化する可能性があります。

透明性、保守性、拡張性が下がる

機械学習は大抵の場合、こういう入力があればああいう出力になるといった結果が、完全には予想しきれないという性質があります。タスクの粒度にもよりますが、その出力をなにか別のアルゴリズムの入力にしようとしたときに、この曖昧さがネックになり得ます。入力が曖昧なので出力も曖昧になる。つまりアルゴリズムをつなげていく中で、機械学習を含むアルゴリズムが途中に挟まっていると、全体にその曖昧さ、不安定さが出てくるようになります。このようにして、内部のデータで何が起こっているかという透明性を失うと、不備が明るみになったときの修正が難しくなるという保守性の問題や、一部に新しいアルゴリズムを適用としたときに全体の流れを把握しづらくなる拡張性の問題が発生します。機械学習の入出力形式が変わる場合は、精度検証なども必要になるため大仕事になるでしょう。

顧客の立場を意識してアウトプットを出す

いろいろなアルゴリズムを学んでいくと、難しいアルゴリズムを使いたくなったり、そういうものを使ったほうが精度が良くなることを期待したりします。ですが、プロダクトを使う側からすれば、内部で何が動いているかは関係ないので、手法にこだわりすぎると時間を浪費する原因になります。

また、アウトプットをどう見せるかによっても、求められる性能(Precision や Recall)が変わってくるため、それによって機械学習手法を設定したり、場合によっては機械学習自体から離れるということも検討したほうがよかったりもするでしょう。

機械学習エンジニアの役割

機械学習で何ができて何ができないのか、またそれにかかるコストはどのくらいかを一番把握しているのは機械学習エンジニアであり、だからこそどうすべきかの判断ができるはずです。

設計段階では、機械学習だからこそのメリットとデメリットを比較して、次に取るべき行動の判断を下す。作業段階では、自身の技術力を用いる。当たり前ですが、闇雲に目の前の仕事をするより、目的を意識して逆算してやるべきことを決めるというのが大事に思えます。

理想の形

機械学習の専門チームを作ると、存在意義として機械学習を使わなければならない意識に、少しはなると思います。

明らかに機械学習でしか実現し得ない事業に取り組んでいるとかではなく、抱えているプロダクトの質を、場合によっては機械学習で向上させたい。そのような場合は、機械学習や分析のできるソフトウェアのエンジニアがいて、開発をしつつ分析を行い、必要な場面で機械学習を用いる。そういう姿こそ、組織として健康的なのかなと感じる日々です。

いい人から脱却して成長したい

YouTube を開いたときに動画一覧に出てきた次の動画に興味を持って観てみました。

www.youtube.com

とても学びがあり、また、話している方に信念やビジョンを強く感じ、非常に魅力的だと思いました。

私はこの動画でいう「いい人」に当てはまっていると思います。動画の通り、良い意味などなく、悪い意味で。
いい人というのは自分の感情や主張だけで動いている人で、相手のことを考えた行動を取れていないということ。いい人という言葉的には性格が良いなどのプラスなイメージですが、ここまで明確に理由をつけてネガティブな意味で言及されている例は初めて目の当たりにしました。そして、自分はここで言及されているいい人の内容に見に覚えしかありませんでした。

動画は恋愛を題材としていましたが、同じことが仕事でも言えると思います。営業職の経験がある人と会話したときに、「営業は、いかに相手の立場になって考えるかということ」という意味合いの話をしていただき、それが記憶に残っていたのですが、今回の動画の話とほぼ共通するな、と感じました。
顧客や仕事仲間の立場になって行動する、それが貢献であり、それをしっかりできる人が仕事ができる人なのでしょうね。


自己評価は悪いことをしないということでいい人だと思っていました。いい人は損をするという話を聞いていて、なぜだろうと思っていました。
相手の立場で考える、ここに成長のためのヒントを垣間見た気がします。

安易に「ヤバい」と言わないように気をつけている話

良い意味でも悪い意味でも世間的によく使われるようになった「ヤバい」という表現。私も、ふとした時に無意識に発言するくらいに馴染んでいます。

最近、といってもここ 1 ~ 2年ですが、発言の際に「ヤバい」を使わないように気をつけています。勿論、ヤバい以外の表現が見当たらず、言い淀んでしまうくらいならば素直に言いますが、別の表現が円滑に出てくるならば、その通りにしています。

いつ使う?

ヤバいとは、次のような場合に使われうるものだと思います。直ぐに思いつくものを挙げてみましたが、他にもあるかもしれません。

  • 程度が甚だしいとき
  • 状況が不都合なとき

一つ目の、程度が甚だしいというのは、良い方にも悪い方にも起こり得るものですので、その両方で使われうるでしょう。例えば、食べたものがとても美味しかったとか、筋トレに精を出して筋肉痛が激しいとか、贈り物に感激したときとかです。最近の体感としては、わりと良い意味で使われる印象があります。

二つ目は基本的に悪い意味で使われます。家に忘れ物をしたとき、欲しい物が高額だと判明したとき、模試の成績が悪かったとき、水たまりでびしょ濡れになったときなどです。

なぜ言わないようにする?

いろいろな表現を使うことで表現力を鍛えたい

安易な表現に傾倒するのは、自身の停滞に繋がると思っています。
自分が不得手とし、理解はできても自発的に使う際に奥底にしまわれている語彙、そういったものを取り出す訓練になり、自分の癖を見直すきっかけにもなるでしょう。

発言の随所で重みをもたせたい

同じ言葉を連発していると、一言ずつの重みが小さくなっていくのでは、と考えています。様々な表現で多角的に表現することで、伝えたい内容に厚みが出てくるはずです。

ではどう言う?

程度が甚だしいとき

「すごい」「とても」「素晴らしい」「激しい」「甚だしい」など、色々な表現があります。

状況が不都合なとき

一言で言い換えるなら、「マズイ」が当てはまると思います。基本そう言い換えて、あとは必要に応じて、別の表現を用いたりするのが理想です。状況が一気に悪くなったときは、「一気に厳しく(キツく)なった」、次第に追い詰められたときは「いつのまにか窮地に...」のような表現ができると思います。

nCk が偶数となるkを探すプログラム

東京大学の入試で出題された数学の問題で、 2015Cm が偶数となる最小の自然数 m を求めさせる問題が存在します。

普通に解いても面白いですが、プログラムでも簡単に nCk に拡張して書けそうだなと思いましたので、しばらく書いていなかった Haskell で書いてみました。

nCk が偶数となる最小の自然数 k を、 n に対してそれぞれ求める。

考察

nCkは次のようにかけます。

\displaystyle {}_{n}\mathrm{C}_{k} = \frac{n(n-1) \cdots (n - k + 1)}{k!}

これは、次のようにも表せます。

\displaystyle {}_{n}\mathrm{C}_{k} = \prod_{i = 1}^{k} \frac{n - i + 1}{i}

従って、nC(k-1) がわかっていると、 nCk を少しの計算で求められます。


\displaystyle {}_{n}\mathrm{C}_{k} = {}_{n}\mathrm{C}_{k - 1} \cdot \frac{n - k + 1}{k} \qquad \cdots (*)

これにより、kを1ずつ増やしながら奇偶の判定を行うことができます。

実装

import Control.Monad

maxN = 2020

odds :: [Integer]
odds = [1,3..]

main :: IO ()
main = do
    putStrLn "n: min k [nCk is even]"
    forM_ (take ((maxN + 1) `div` 2) odds) $ \n -> do
        putStrLn $ show n ++ ": " ++ show (loop n 1 1)

loop :: Integer -> Integer -> Integer -> Integer
loop n k t =
    let nt = t * (n - k + 1) `div` k in
    if nt `mod` 2 == 0 then
        k
    else if n <= k then
        -1
    else
        loop n (k + 1) nt

(*) の式を使い、loop で kを1ずつ増やしながら奇偶をチェックしています。偶数となったら k を返せば、nに対して、題意のkを得られます。

補足

実は、 nC(k-1) が奇数の場合、nCk の奇偶は (n - k + 1) / k の奇偶に一致するため、 loop 中の t として保存している nCk の値は必要ないのですが、プログラムの意図を分かりやすくするために敢えて書いています。

これも分かり易さのために省略していますが、 nCk = nC(n-k) であることを考えれば、kはnまででなく、n/2まで調べれば良いこともわかります。

結果

上記プログラムでは 2020 までの奇数を選んで n とし、 最小の k を求めています。

出力の最後の方 (2000 ~) は次の通り、

2001: 2
2003: 4
2005: 2
2007: 8
2009: 2
2011: 4
2013: 2
2015: 32
2017: 2
2019: 4

n = 2015 のとき、題を満たす k は 32 です。

見た感じ、n+1 に素因数2をどれだけ含んでいるかが鍵となりそうです。

また、 n = 2^m - 1 のときは、どれも -1 が出力されていました。つまり k 無し。この辺りで問題も作れそうです。

超がつく怠け者の AppleWatch 使用日記

基本、今まで何かを体に身につけるのを厭うていた私ですが、 Apple Watch Series 5 を昨年購入し、1年ほど使っています。

何が良かったのかをまとめます。

一番はモバイルSuica

財布を取り出す操作を面倒臭がった

生活を大きく変えたのは、モバイルSuicaです。

最初、その存在や機能を知らず、ほとんど財布を使って支払いを行っていました。

ある日、 View カードを契約しました。クレジットカードの中に Suica が入っており、使いやすそう、活用してみたいと思いました。

View カードは、駅などにある端末で設定を行えば、金額が閾値を下回ると自動チャージもしてくれるということで、支払いが大きく変わると思ったのですが、どうやら駅の改札を通るときにしかチャージできず、 PASMO で定期を使っていること、電車に乗らないときもあることを考慮すれば、あまり使い勝手が良くないのでは、という結論に至りました。

それから色々と情報収集を重ねて行って、モバイルSuicaに行き着きました。

持っていた iPhone 7 に入ること、スマホでチャージと決済ができることということで、その時からモバイルSuicaを活用しています。

iPhone すら取り出すのを面倒臭がった

Suica は、使えないところがあるものの、コンビニなどではまず使えるため、財布を取り出す機会をかなり減らすことができました。これは大きなことで、毎回小銭を探して取り出す操作やお釣りを入れたりする操作を止められるということだけでなく、小銭がパンパンにならないような注意を払ったり、定期的に銀行からお金をおろしたりという手間も省けます。

しばらくは iPhone で便利にモバイルSuicaを活用していたのですが、面倒くさがりの私はついに、「iPhone を取り出すのすら面倒くさい」と思うようになりました。

調べていると、 Apple Watch でモバイルSuicaが使えることがわかり、更に数カ月後に Apple Watch の新作 Series 5 が発売されました。

時計を身につけるのは手間がかかるし、気がかりが増えるから嫌だな、と思っていたのですが、色々考え抜いて購入する決断をしました。

iPhone に入っている SuicaApple Watch に入っている Suica は別物です。それぞれにチャージする必要があるのですが、ボタン一つでチャージできるため、手間はそんなにありません。

場合によって、 iPhone を使ったり Watch を使ったりで、買い物などが快適に行なえます。

付随して得られた利点

もともとモバイルSuicaを目的に購入した Apple Watch ですが、別の機能もいくつか役に立っています。

まずは時間確認です。意外と、スマホを出すまでもないけど、ちょっと時間を確認したいという機会がいくつかあることに気が付きました。時間なんてスマホで確認すればよいと思っていたので、意外な気づきです。

次に、 Mac のロック解除です。 同じアカウントを使っている場合、 Apple Watch を身に着けていると、 ロックの解除を自動的に行なってくれます(再起動時などは別)。 Mac を数台持っている私にとってこれは大きい。

そして、アクティビティです。消費カロリーや運動量を記録してくれています。わりと気になって見ており、でかけるときの一つの楽しみとなっています。

時計をする手間ですが、これによってお出かけの気分が高まる気がするので、案外悪くないな、と思うようになりました。

買ってみて

Apple Watch は 5万円くらいしたため安い買い物ではありませんが、今ではすっかり生活の一部に入り込んでいます。

スマホ、タブレット、パソコンのストレージ戦略(Apple 端末)

スマホタブレット、パソコンを購入するときに、ストレージをどうするかというのはいつも迷います。

そこで、私の所感を、備忘録を兼ねて共有しておきます。時代によって変化するので、 2020 年版とします。

勿論、使い方によって必要な容量など変わってしまうので、これが正しいというわけではありません。悩んでいる方の最後のひと押しくらいになればと思います。

そもそも容量が多いに越したことはない

当たり前のようですが、容量が多くて困ることはほぼ無いと思われます。全てを使い切る義務なんて言うのはありませんからね。予算が無限の人は最大容量のものを買えばよいです。

容量が多いモデルを選択するときに、悩む理由は値段でしょう。したがって、ここでは、空き容量に余裕をもたせながら値段を抑える方針とします。

スマホの容量

結論:128 GB くらい欲しい

今回は iPhone での話になります。 iPhone は SD カードを入れる場所がないため、物理的には容量を拡張できず、クラウドなどを活用することになります。

私の場合は、カメラで撮った写真を 200 枚程度保存しており、その他は2段階認証用のアプリとか、パズルゲームとか、天気や路線、電子決済などの生活に必要なアプリを入れています。これとシステムで既に 30 GBを使用しています。

私は、写真撮影に Pixel も使っているため、写真 200 枚は少ないほうだと思います。しかし、よく出かける方はもっと撮影されているでしょう。数千枚ほどでしょうか。また、ゲームを複数入れてスマホでよくゲームする場合もあるでしょう。こういった要素があると、64 GB に到達してしまうのは時間の問題です。

注意していただきたいのは、記載されている容量の全てが、写真などの自身のコンテンツに使えるわけではありません。最初から入っている iOS やデフォルトのアプリケーションでいくらか容量を使ってしまっているため、実際に使えるのは記載の容量を下回ります。

また、容量ビッタリを使い切ることはまずなく、限界付近に到達した場合は、要らないデータなどを頻繁に消したりしながら新しいデータを入れることになります。これは結構なストレスになります。容量ギリギリになりそうな場合は、1段階上のものを選択するのが良いと考えています。

128 GB まで増やせば大体の場合は大丈夫ではないでしょうか。

タブレットの容量

結論: 256 GB くらい欲しい

いろいろな用途があると思いますので、私の使い方を挙げます。

iPad で行っていることは、書籍アプリで読書をする、ゲームをする、イラストを描く、などです。ゲームは1つ 10 GB くらいの容量を使用する場合も多く、複数入れると結構ストレージを圧迫します。また、書籍アプリに沢山のデータを入れておくと、それも数十GBくらい使うことになります。

使い方によっては、 128 GB モデルでも良いかもしれませんが、なにか新しいことを始めようとなった場合などを考えて、 256 GB あったほうが安心できそうです。

あるいは、沢山のデータを用いてメディアクリエイトを行ったりする場合は、 512 GB も選択肢に入れてるのもありかと。 iPad で動画を作成されている方もいらっしゃるようです。

パソコンの容量

結論: 1TB くらい欲しい

これも用途が様々ですね。 YouTube を見るだけしか使わないという人は 256 GB くらいの容量を選択しても良さそうです。

スマホタブレットと比べて、外部ストレージを用いやすいため、しばらく使わないデータなどを外に出してやることができます。それでも、私は 1TB くらいあったほうが良いのではと考えています。

私の場合、プログラミングの開発環境を色々入れたり、音楽ソフト、音源、イラストソフト、 Adobe CC などを入れています。こういったシステムの内部に保存されるようなデータは、外に出すことが現実的ではありません。したがって、パソコンの容量を使用します。

外部ストレージを使う場合、データのやり取りを行う場合に、一旦はローカルストレージを使用する場面というのは出てきます。パソコン自体の容量がギリギリだと、そもそもデータのやり取りが上手く行えなかったり、何回かに分ける手間などが発生します。数十〜数百くらいは余裕をもたせておいたほうが良いように思えます。

パソコンの容量がいっぱいになったとき、データを整理するのは大変です。使わなくなったデータがどこかに有るか探したり、このデータは必要かと1ファイルずつ見ていくのは根本的な解決になりにくいはずです。アプリとデータが密に結びついていないための難点です。

これらのことを考慮して、512 GB、できれば 1TB という結論です。