神戸市データサイエンティスト募集要項(完全転載)

下記ページの完全転載です。消される前に永久保存です。EBPM分野のデータサイエンティストの業務内容や待遇のベンチマークとして参考にしてください。 www.city.kobe.lg.jp

記者資料提供(令和元年6月26日) 企画調整局産学連携ラボ

データサイエンティストを募集します

 神戸市では、オープンデータや統計の公開・活用により市民や事業者のニーズを踏まえ、根拠に基づいた政策立案(EBPM)を推進する目的で、行政保有のデータや民間保有のデータ等を利活用し、施策を推進していく人材を募集します。

1.募集内容

(1)職  種:データサイエンティスト
(2)募集人員:1名
(3)主な業務内容
1.データに基づいた神戸市政へのニーズ把握、政策・地域課題の発見および分析
2.最適な政策立案のためのソリューションの提案・助言
3.定量(KPI)管理等によるプロジェクトマネジメント
4.データ予測による意思決定の迅速化の支援
5.神戸市関係部局のデータの一元的管理に向けた検討・助言
6.その他前各号に掲げるもののほか、EBPM推進に関する事項等
(4)委嘱期間:令和元年8月1日~令和2年3月31日(出務日については応相談)
(5)勤務場所:神戸市企画調整局産学連携ラボ内
(6)募集期間:令和元年6月26日(水曜)~7月8日(月曜) 17:00まで
※ データサイエンティストは地方公務員法第3条第3項に基づく非常勤の嘱託職員です
※ 勤務状況が良好な場合は、翌年度以降も、委嘱期間を1年毎に更新する場合があります
(上限3年、令和4年3月31日まで)
※ 分析対象として、市の有する税情報を含みます
※ 選考の結果、適任の方がいない場合は、委嘱を見合わせることがあります

2.応募資格

(1)民間企業・自治体において、データ分析に基づくプロジェクトマネジメントの実務経験を持つこと(大学・研究機関等に在籍し、民間企業・自治体との共同研究によりデータ分析に基づく提案を行った場合も含む)。
(2)地方公務員法第16条に規定する欠格条項に該当しないこと
地方公務員法第16条(抜粋)
次の各号一に該当する者は、条例で定める場合を除くほか、職員となり、又競争試験若しくは選考を受けることができない。
1.成年被後見人又は被保佐人
2.禁錮以上の刑に処せられ、その執行を終わるまで又はその執行を受けることがなくなるまでの者
3.当該地方公共団体において懲戒免職の処分を受け、当該処分の日から2年を経過しない者
4.人事委員会または公平委員会の委員の職にあって、第五章に規定する罪を犯し刑に処せられた者
5.日本国憲法施行の日以後において、日本国憲法又はその下に成立した政府を暴力で破壊することを主張する政党その他の団体を結成し、又はこれに加入した者

3.選考方法

選考方法:個別面接
選考内容:データサイエンティストとしての適性を総合的に審査し、最終合格者を決定します。
実施日時:令和元年7月11日(木曜) 午後
※ 実施日時・場所等の詳細については、メール等により通知します。
※ 応募者多数の場合は、書類選考を行う場合があります
合格発表:選考の結果は、受験者全員に令和元年7月中旬までにメール等により通知します。

4.報酬等

(1)勤務日数:週1日 ただし必要に応じて休日出勤有り
※最終合格者に対し、希望する勤務日数を相談させていただきます
※勤務時間は、8時45分~17時30分(休憩1時間)です
※但し、土曜日、日曜日、祝日、年末年始(12月29日から1月3日)は除きます
※具体的な出務日は、選考合格後、最終合格者と相談のうえ決定します
(2)報酬:【年俸額】約75万円 【月 額】約10万円

※大学院卒・30歳・民間経験6年の場合の例
※報酬は、最終学歴・経歴(職務内容・期間)に応じて、一定の基準により決定します
※別途、通勤費を支給します
(3) 休 暇:年次有給休暇、夏季休暇、結婚休暇など
年次有給休暇は、3日(休暇15日×1/5=3日)
(4) その他:社会保険等有。ただし勤務条件による。

5.申込手続

(1) 申込書類:選考申込書兼職務経歴書(指定様式)
(2) 申込期間:令和元年6月26日(水曜)~7月8日(月曜) 17:00まで
(3) 申込方法:申込期間内に選考申込書兼職務経歴書をご提出ください。
(4) 注意事項等:
1.選考結果及び理由についての電話及びメール等によるお問い合わせは一切受け付けません。
2.選考実施に関して収集した個人情報は、本選考の円滑な遂行のために用い、神戸市個人情報保護条例に基づき適正に管理します。
3.申込手続きに不備がある場合は、応募が無効となります。
4.受験資格がないことや申し込みの内容に虚偽があると認められた場合など合格を取り消すことがあります。

6.採用までのスケジュール

選考申込書配布開始 令和元年6月26日(水曜)
選考申込書受付    令和元年6月26日(水曜)~7月8日(月曜) 17:00まで
選考(個別面接)    令和元年7月11日(木曜) 午後
合格発表         令和元年7月中旬     <予定>
採用(委嘱)       令和元年8月1日 (木曜) <予定>

7.FAQ

Q.今勤めている会社に私が受験することを伝えていないのですが、神戸市は秘密を守ってくれますか。
A.いただいた個人情報は、選考申込書記載の連絡先に確認の連絡をとること以外には使用しません。また、外部からの問い合わせに対し、応募の有無も含め個人情報についてお答えすることはありません。ただし、最終合格者については、採用までに職歴証明書を提出いただくなど、職務経歴について確認させていただきます。
Q.兼業は可能ですか。
A.兼業は可能です。ただし、勤め先がある場合には、第一次選考を通過した時点で、なるべく会社並びに所属団体等との調整を始めてください。
Q.委嘱期間は年度毎の更新のようですが、最長何年間委嘱されますか。
A.委嘱期間は最長3年です。ただし、翌年度以降の委嘱の有無については、予算の議決、仕事の成果、その他の状況にもよります。したがって、勤務成績が良好でも、翌年度以降の委嘱が保証できない場合があります。
Q.遠隔地から通勤の場合、宿泊費は支給されますか。
A.宿泊費は支給されません。通勤費は支給します。

【申込書類の提出先・問合せ先】

〒650-8570
神戸市中央区加納町6-5-1(神戸市役所1号館12階)
神戸市市企画調整局産学連携ラボ:山下・服部
TEL:078-322-6462
E-mail:ict-sozo@office.city.kobe.lg.jp

就任者情報: 神戸市による紹介 www.city.kobe.lg.jp

ご本人によるブログ note.mu

ARIMAXの使い方

モチベーション

職場でいきなり時系列モデルのPOCをやることになり、時系列分析初心者だったので大変な思いをした。exogenousやら外生変数やら何だかおどろおどろしい用語が出てきて怖気付きそうだったがPythonなら一発だった。Python愛がここでも深まった。

時系列モデルのデファクトスタンダード、ARIMAに外生変数を追加して精度の向上を目指すARIMAXモデルの直感的解説と使い方を下記Kaggleカーネルをベースにまとめます。

www.kaggle.com

ARIMA + X = ARIMAX

機械学習常習者的直感的解釈

X = exogenous variable (外生変数)

イメージとしては教師ラベルとしてのyを入力するだけのものはARIMA, yに並行して説明変数としてのXも同時入力するものはARIMAXということになる。機械学習に慣れた親しんできた者(機械学習常習者)から見ると、教師ラベルだけで学習を進めようとするARIMAはかなりエキセントリックなことをやっているように見え、むしろARIMAXの方が普通(スタンダード)に見える。

そもそも時系列モデルの数式ではXがなかなか出てこない。これはYのYによるYのための自己回帰モデルだからだが、機械学習常習者から見るとどこか落ち着かない。

Pythonによる実装

arima = sm.tsa.statespace.SARIMAX(y, order=(7,1,7), seasonal_order=(0,0,0,0), enforce_stationarity=False, enforce_invertibility=False).fit()

arimax = sm.tsa.statespace.SARIMAX(y, order=(7,1,7), seasonal_order=(0,0,0,0), exog = X, enforce_stationarity=False, enforce_invertibility=False).fit()

ちなみにXはpandas.DataFrameでもnumpy.ndarrayでもOK。 ちなみに実際にはXはX_trainとX_testに分割し、fitの段ではX_trainを、predictの段ではX_testをそれぞれ入力データとしてモデルに与えてやる必要あり。

参考になった書籍

経済・ファイナンスデータの計量時系列分析 (統計ライブラリー)

経済・ファイナンスデータの計量時系列分析 (統計ライブラリー)

時系列解析入門

時系列解析入門

docker containerはdocker imageの写像である

前提知識

  • docker containerはdocker imageの写像である
  • 作業はdocker containerの中に入って行うのであってdocker imageの中で行うのではない
  • docker imageからdocker containerを作り、docker containerの中に入って作業をするのであって、docker imageの中に入って作業をするのではない
  • docker containerの中で環境を変更した場合、その変更履歴はdocker containerの中に保存されるのであって、そのdocker containerを作った元ネタであるdocker imageに変更した環境が保存されることは無い。従って例えば1日目の作業が終了しexitした後、翌日また同じdocker imageを走らせようと"$ docker run IMAGE"としても前日追加で入れたはずの〇〇というライブラリは存在していない。それはdocker containerのほうに保存されている。

よく使うコマンド集

$ docker images

利用可能なdocker imageのリストを表示させる

$ docker run IMAGE

IMAGEという名のdocker imageからdocker containerが自動生成される
このとき生成されるdocker containerのエイリアス(別名)も自動生成される(ランダムに適当な名前が付与される)。以後このエイリアス(別名)を指定することでこのdocker containerに対する指示が出せる。(e.g., $ docker start -i CONTAINER)

カレントワーキングディレクトリとdocker containerのワーキングディレクトリをマウントさせて、カレントワーキングディレクトリ内のファイルをdocker containerの中から普通に利用できるようにしたいときは、

$ docker run -v {PATH TO YOUR CURRENT WORKING DIRECTORY}:{PATH TO CONTAINER'S WORKING DIRECOTRY} IMAGE  

とする

$ docker ps

起動中のdocker containerのリストを表示させる

$ docker ps -a

起動中/停止中のdocker containerのリストを表示させる

$ docker start CONTAINER

CONTAINERという名のdocker containerを起動させる

$ docker attach CONTAINER

起動中のCONTAINERという名のdocker containerの中に入る

$ docker start -i CONTAINER

CONTAINERという名のdocker containerを起動させ、なおかつその中に入る

具体的な使用例

シナリオ)tensorflow_dockerという名前のimageからcontainerを作成し、その中に入ってjupyter notebookを起動して作業したい

初回

$ docker images  
$ docker run -v {PATH TO YOUR CURRENT WORKING DIRECTORY}:{PATH TO CONTAINER'S WORKING DIRECOTRY} tensorflow_docker  
$ jupyter notebook --ip=0.0.0.0 --allow-root

次回以降

$ docker ps -a  
$ docker start -i hoge  
$ jupyter notebook --ip=0.0.0.0 --allow-root

RNN or from front to back time series reading

The structure of RNN shows that the previous node connects to the current node. This connection is drawn in 2-dimension such that the previous node sits in the left side and the current node sits in the right side. f:id:HealthcareIT_interpreter:20190216122258p:plain However, when you see the input tensor, the structure of it is 3-dimension such that the previous input sits in the front and the current input sits in the back.

In [1]: tensor                                                                  
Out[1]: 
array([[[3, 7],
        [7, 0],
        [2, 0],
        [3, 9],
        [1, 2]],

       [[4, 4],
        [6, 0],
        [2, 4],
        [3, 4],
        [3, 0]]])

In [2]: tensor.shape                                                            
Out[2]: (2, 5, 2)

So if you revisit the RNN structure as the same as that of the tensor (3-dimension), you can draw the previous node in the front, whereas the current one in the back. This gives me the new insight that when you read a sentence you can imagine that the words stream in aligning with the front-back line, which is different from streaming in aligning with the left-right line as shown in your text. This insight may improve one's reading ability. For human's brain, the movement from left to right (or from right to left as well as from up to down) is not natural as human walks from back to front. Having this insight, I tried to read the novel and checked how my reading fluency improved.

www.aozora.gr.jp

By imagining the words stream from back to front, the kind of obsession that you have to move your eye focus from left to right has been alleviated. This alleviation makes me concentrate on just grasping the meaning of the sentence. I can name this reading method as "RNN reading". I want to know how a person with dyslexia feels when he/she tries reading using this method.

How can you trim the file size of ipynb which is so big that your kernel cannot open it?

I was working on multi-variate regression analysis. There were over 80 explanatory variables so I used the AIC (Akaike information criterion) with step function in order to reduce these. BTW, the AIC step function does not exist in Python so you have to write yourself.

qiita.com This guy wrote his own step function. I copied and pasted it in my ipynb.

def step_aic(model, exog, endog, **kwargs):
    """
    This select the best exogenous variables with AIC
    Both exog and endog values can be either str or list.
    (Endog list is for the Binomial family.)

    Note: This adopt only "forward" selection

    Args:
        model: model from statsmodels.formula.api
        exog (str or list): exogenous variables
        endog (str or list): endogenous variables
        kwargs: extra keyword argments for model (e.g., data, family)

    Returns:
        model: a model that seems to have the smallest AIC
    """

    # convert exog, endog to list format
    exog = np.r_[[exog]].flatten()
    endog = np.r_[[endog]].flatten()
    remaining = set(exog)
    selected = []  # contains adopted candidates

    # calculate AIC only for constants
    formula_head = ' + '.join(endog) + ' ~ '
    formula = formula_head + '1'
    aic = model(formula=formula, **kwargs).fit().aic
    print('AIC: {}, formula: {}'.format(round(aic, 3), formula))

    current_score, best_new_score = np.ones(2) * aic

    # adopt all elements, or ends the loop if the AIC will not be improved although adding any elements
    while remaining and current_score == best_new_score:
        scores_with_candidates = []
        for candidate in remaining:

            # calculate the AIC when adding the remained elements one by one
            formula_tail = ' + '.join(selected + [candidate])
            formula = formula_head + formula_tail
            aic = model(formula=formula, **kwargs).fit().aic
            print('AIC: {}, formula: {}'.format(round(aic, 3), formula))

            scores_with_candidates.append((aic, candidate))

        # adopt the elements that improved the AIC most as the best candidate 
        scores_with_candidates.sort()
        scores_with_candidates.reverse()
        best_new_score, best_candidate = scores_with_candidates.pop()

        # if adding a candinate reduces the AIC, add it as the determined candidates 
        if best_new_score < current_score:
            remaining.remove(best_candidate)
            selected.append(best_candidate)
            current_score = best_new_score

    formula = formula_head + ' + '.join(selected)
    print('The best formula: {}'.format(formula))
    return model(formula, **kwargs).fit()

Here is the problem. "print('AIC: {}, formula: {}'.format(round(aic, 3), formula))" yeilds huge amount of text information on my notebook, which makes my file as big as 80 MB. Have you ever heard of 80 MB sized ipynb? Jupyter notebook cannot handle it and freezed. To solve this problem, you have to trim your ipynb. But how? Your local jupyter kernel cannot open it. I tried once to delete unnecessary part manually by opening ipynb in my editor (as a JSON file) but that forced me huge efforts.

github.com

My idea was to use Google Colab notebook. Colab can handle and open a big size file.

You can use Google Colab Notebooks for trimming outputs. I opened 83 MB ipynb file at Colab and Colab could handle it. From Colab GUI, you can choose the output cell you want to delete then get the file back to your local directory and reopen it. Eventually I trimmed the original file to the size of 2 MB in this way.

ブログタイトルを変更しました

今年2月から転職をし、病院から外資系企業に籍を移すことになりました。もう医療通訳で診察室に呼ばれることはなくなりましたが、その代わり海外のスタッフと英語でやり取りすることが日常的になり、ますます汗だくになっております。特にテレフォンカンファレンス(TC)で相手がインド英語やフランスなまりの英語だったりすると聞き取ることすら難しい状態です。データアナリストとして日々精進していきますので今後もよろしくお願いします。

現在の取得資格: 医療情報技師(2016年8月試験合格), 診療情報管理士(2018年2月試験合格、88期生)

あ、医療情報技師の点数取得どうしよう。医療情報学会行かないと…。その点、診療情報管理士は資格維持コストが無いので楽ですね。同期の皆さんよろしくお願いします。

診療情報管理士認定試験の合格者受験番号一覧をPhantomJSでスクショしようとしたらブロックされた

3月23日に診療情報管理士認定試験の合格者受験番号が発表されました。認定試験のホームページに掲載されております。

f:id:HealthcareIT_interpreter:20180325184734p:plain

よーし、こりゃあWebscrapingしがいがあるのー、ということで、小手調べにPhantomJSでスクリーショットを撮って見よー、と試して見たことろブロックがかかってしまいました。

from selenium import webdriver
from selenium.webdriver.common.keys import Keys as keys
import time

def main():
    url = "https://www.jha-e.com/top/certExams/resultDetails"
    
    driver = webdriver.PhantomJS()
    driver.get(url)
    
    print(driver.current_url)
    
    driver.save_screenshot("testnum.jpg")
    driver.quit()
    
    print("end")


if __name__ == '__main__':
    main()

f:id:HealthcareIT_interpreter:20180325183111j:plain

やっぱセキュリティ気にしてるのかな?このはてなブログにリンク貼ることもできないようです。

www.jha-e.com

ちなみにurlを一つ上の階層の"https://www.jha-e.com/top/certExams/result"にして見たらちゃんとスクショ撮れました。

f:id:HealthcareIT_interpreter:20180325183120j:plain