VSCode + Mac + pyenv + pipenv な環境構築メモ - 2021

「これがベストプラクティスだ」という主張ではなく、この組み合わせでやるなら... という設定メモです。

はじめに

pyenv

単一の version でよければ、brew が楽だとは思う。 複数のversion をインストールしたいケースを考えて、今回は pyenv を選択。

Pipenv

Pipenv: Python Dev Workflow for Humans — pipenv 2021.5.29 documentation

Pipenv is a tool that aims to bring the best of all packaging worlds (bundler, composer, npm, cargo, yarn, etc.) to the Python world.

ロックとかできるのはいいよね。

こんな話もあるので、歴史的背景は押さえておきたい。

vaaaaaanquish.hatenablog.com

設定

インストール

まずは Python をインストール。

pyenv install 3.9.5

プロジェクトディレクトリに移動して...

cd your_project_dir
pyenv local 3.9.5

pipでpipenvをインストールする。

pip install pipenv

仮想環境

Pythonのversionを指定して、新しい 仮想環境をpipenv で作成する。

export PIPENV_VENV_IN_PROJECT=true
pipenv --python 3.9.5

これで、ワーキングディレクトリに 仮想環境として .venv ディレクトリが作成される。 PIPENV_VENV_IN_PROJECT は .bashrc や .zshrc に設定しておくとよい。

VSCode

インタープリターの選択で、.venv/bin/python を指定すればよい。

Terminal

仮想環境をactivate すればよく、例えば

. ./.venv/bin/activate

あるいは、

 pipenv shel

でよい。

Recurrent neural network based language model

ChainerのRNN Language Models — Chainer 4.3.1 documentationを動かすにあたり、元論文を読んでみることにした。

明確なリファレンスは見当たらなかったが、恐らく "Mikolov, Tomáš / Karafiát, Martin / Burget, Lukáš / Černocký, Jan / Khudanpur, Sanjeev (2010): "Recurrent neural network based language model", In INTERSPEECH-2010, 1045-1048. ではないかと思う。

論文抄録

1.論文の概要

Recurrent neural networkに基づく言語モデル(RNNLM)の音声認識への応用。 複数のRNN LMを組み合わせることで、backoff language modelと比較して、約50%のperplexityの削減が見込める。 Wall Street Journal taskにおける音声認識実験では約18%の単語エラーの減少を示した。

2. 問題設定と解決した点

シーケンシャルデータ予測はML/AIにおいて重要な問題設定。 統計的言語モデルの目的はテキストデータにおいて文脈上の次の単語を予測すること。 従来提示された高度な言語モデリング技術の大半は、ベースラインをわずかに超える改善しかしめせず、実用的ではなかった。

3. 技術や手法のキモ

simple recurrent neural network を採用した。 入力層がx, 隠れ層がs, 出力層がyで、時刻tの入力がx(t), 状態がs(t), 出力がy(t) となる。 順伝播計算は以下の通り。

(1) 
 x(t) = w(t) + s(t-1)

(2) 
  s_j(t) = f(\sum_{i} x_i(t) u_j)

(3) 
  y_k(t) = g(\sum_{j} s_j(t) v_k)

w(t)はone-hot vector。隠れ層sのユニットは30-500。

4. 主張の有効性検証

WSJとNIST RT05で実験を行っている。

読み終えて...

ChainerのExampleで紹介している Recurrent Neural Net Language Model のベースには違いないと思われるが、ExampleにはWord Embedding Matrixが追加されていたり、活性化関数がsigmoidではなくtanhだったり、と細かな違いはあった。

そもそも論文を読み慣れてないし、まとめ慣れてないのでだいぶ戸惑った。 抄録フォーマットも力付きて、全部埋めきれず。何回かやれば慣れると思うが。

リファレンス

抄録フォーマットは以下を参考にさせてもらった。

メモ:PyCharmの設定

PyCharmが素晴らしいという話を聞くので、お試しで使ってみる。

環境

Flake8と統合

  1. Preferences > Tools > External Tools で + マークを押す
  2. Tool Settings で 下記を設定する
  - Program: Flake8の実行ファイル
  - Arguments: $FileDir$/$FileName$ など
  - Working directory: 通常はプロジェクトのルートかな

パッケージのインポート

PyPIに公開されているパッケージは簡単だが、プロジェクト外にある自前パッケージを認識させるのがやや難儀。

f:id:kotaroito2002:20180713161221j:plain

  1. Project Interpreterを選択
  2. 設定アイコンで "Show All..." を選択
  3. "Show paths for the selected Interpreter" を選択

"Interpreter Paths"のダイアログが出現するので、目的のパッケージを追加する。

我が家のフォトストレージ構成 - 2018年版

HDDが壊れてデータリカバリーをする羽目になり、だいぶ金銭的にダメージを負ったので、再発防止としてフォトストレージを見直すことにした。

構成

f:id:kotaroito2002:20180503135247p:plain

写真整理や共有のしやすさを考えて、Google Photoをプライマリーストレージとし、全ての写真を集約することにした。 人的作業ミス(うっかり全削除など)が発生することを考慮し、Amazon Prime Photoをセカンダリーストレージとしている。

ローカルにも保管しておくが、故障や紛失は発生する前提で。あくまで tmp ディレクトリだと考える。

アップロード

自分が所有するスマホからのアップロードは、Google Photo と Prime Photoのクライアントアプリを入れて自動アップロードにした。

デジカメや家族所有のスマホからのアップロードはMacBookに集約する。 MacBookにはGoogle Backup and Sync と Amazon Drive アプリをインストールし、「ピクチャ」と「ムービー」をバックアップフォルダとして設定する。

Google Backup and Sync

f:id:kotaroito2002:20180503140525p:plain

Amazon Drive

f:id:kotaroito2002:20180503140414p:plain

ディレクト

MacBookの「ピクチャ」と「ムービー」は、年単位でディレクトリを切っておく。 家族のスマホやデジカメからインポートしてくる時は、イベントが終わったらその年のフォルダに放り込めばよい。あとはGoogle Backup and Sync と Amazon Drive がよしなにアップロードしてくれる。

f:id:kotaroito2002:20180503140755p:plain

RailsなプロジェクトでReact.jsを利用する1つの例

2016年当時それなりに苦労してRails4.xにReact.jsを導入しましたが、記録に残し忘れていたので、今さらながらブログに書いてみようかと思います。

構成

React.jsを導入するだけならGemからインストールするのが楽なのですが、後日様々なNodeパッケージを導入する可能性を考えて、全てpackage.jsonで管理することにしました。 一方でアセットの配信は既存の仕組みに乗っかりたかったので、assetの配信はSprocketsにお任せすることに。

Node

Rubyはrbenvでインストールしていたので、Nodeもndenvを使うことにしました。

Webpack + Babel

ReactのコンポーネントはES6で書きたくなるので、Webpack + Babelでトランスパイルしています。

react-rails

react_component というViewHelperが便利なので、これを使うためだけにインストールしています。

ディレクト

app/frontend を新たに作成し、ここにReactコンポーネントのソースを格納しています。

├── app
│   ├── assets
│   │   ├── images
│   │   ├── javascripts
│   │   └── stylesheets
│   ├── frontend
│   │   ├── src
│   │   └── test
├── config
│   └── webpack
│       ├── development.js
│       └── production.js
├── package.json

設定

主な設定を書いておきます。2年前なので若干古いかもしれません。。

.babelrc

{
  "presets": ["env", "react"],
  "env": {
    "development": {
      "plugins": [
        "react-hot-loader/babel"
      ]
    }
  }
}

package.json

{
  "version": "1.0.0",
  "scripts": {
    "start": "webpack --config config/webpack/development.js --hot",
    "release": "webpack --config config/webpack/production.js",
    "test": "npm run mocha",
    "bundle-size-analyzer": "webpack --config config/webpack/production.js --json | webpack-bundle-size-analyzer",
    "mocha": "NODE_ENV=test mocha --compilers js:babel-register --require app/frontend/test/setup.js app/frontend/test/**/*.spec.js"
  }
}

config/webpack/development.js

const webpack = require('webpack');

module.exports = {
  entry: [
    './app/frontend/src/components.js'
  ],
  output: {
    path: './app/assets/javascripts/build',
    filename: 'components.js'
  },
  watch: true,
  module: {
    loaders: [{
      test: /\.jsx?$/,
      exclude: /node_modules/,
      loaders: ["babel-loader"]
    }]
  },
  resolve: {
    extensions: ['', '.js', '.jsx']
  }
}

開発

開発に必要な準備は(nodeのインストールを除けば) npm install && npm start するだけです。

エントリーポイントになっている component.js でrequireしておき、

// app/frontend/src/components.js
window.React = require('react');
window.ReactDOM = require('react-dom');
window.PropTypes = require('prop-types');
window.MyApp = Object.assign(
  {
    MyAwesomeComponent: require('./components/MyAwesomeComponent').default
  }
);

Railsのviewでreact_componentを呼び出します。

react_component('MyApp.MyAwesomeComponent', {})

デプロイ

capistranoに下記タスクを追加することで、deploy:compile_assets の前に webpack --config config/webpack/production.js が走ります。

# lib/capistrano/tasks/webpack.rake
namespace :webpack do
  desc "Release build"
  task :build_release do
    on roles(fetch(:ndenv_roles, :all)) do
      within release_path do
        execute :npm, 'run', 'release'
      end
    end
  end

  before 'deploy:compile_assets', 'webpack:build_release'
end

結果、app/assets/jabascripts/build/components.js にファイルが出力されるので、あとはアセットパイプラインのお仕事です。

まとめ

書き殴りになってしまいましたが、RailsなプロジェクトでReact.jsを利用している事例を書いてみました。 2018年に何をいまさら感はありますが、自分の備忘録として。

AWS KMSを利用して、S3に暗号化オブジェクトを保存する

AWSでシークレットを安全に管理・配備する方法として、AWS KMSについて調査したので、そのメモを残しておきます。

AWS KMS

データの暗号化に使用される暗号化キーの作成と管理を容易にするマネージド型サービスで、S3をはじめ様々なAWSサービスと統合されています。 最初の取っ掛かりとして、この記事が分かりやすいです。

dev.classmethod.jp

AWS KMS + S3

Amazon Simple Storage Service (Amazon S3) で AWS KMS を使用する方法 に記載の通り、S3で AWS KMS を使用する方法は、「サーバー側の暗号化: SSE-KMS の使用」「Amazon S3 暗号化クライアントの使用」の2通りあります。それぞれ具体的な方法を見ていきたいと思います。

サーバー側の暗号化: SSE-KMS の使用

AWS SDK, AWS-CLI, S3コンソールなどを利用することで、サーバー側で暗号化を行えます。 最もカンタンな例として、AWS-CLIでの暗号化・復号化をしてみました。

暗号化

aws s3 cp plain.txt s3://${YOUR_S3_BUCKET} \
    --sse-kms-key-id ${YOUR_AWS_KMS_KEY_ID} \
    --sse aws:kms

復号化

aws s3 cp s3://${YOUR_S3_BUCKET} plain.txt \
    --sse-kms-key-id ${YOUR_AWS_KMS_KEY_ID} \
    --sse aws:kms

cp — AWS CLI 1.14.58 Command Reference

Amazon S3 暗号化クライアントの使用

Amazon KMS で保管されるカスタマーマスターキーを利用し、エンベロープ暗号化 を用いてオブジェクトをS3に保管する方法です。

AWS SDK for Rubyも対応しているので、Rubyで扱うことも可能です。

技術的な詳細

エンベロープ暗号化については、下記ドキュメントを読むと良いです。

https://docs.aws.amazon.com/ja_jp/kms/latest/developerguide/images/envelope-encryption.png 出典: AWS Key Management Service の概念

事例

blog.honeybadger.io

RubyMineの設定メモ

備忘のためにメモっておく。

Rubymineをインストールしたら最初にやるオススメ設定 - Qiita

RubyMineで参照するRubyのバージョンをrbenvのRubyに変更する - Qiita

RubyMineからbundle execする方法 - くりにっき