読者です 読者をやめる 読者になる 読者になる

UUUM攻殻機動隊

UUUMのエンジニアによる技術ブログです

Railsアプリ開発中に思い出す、StrategyとRackミドルウェア

こんにちは、エンジニアのナカハシです。

最近は、しばらくRailsでのWebアプリ開発に勤しんでいる毎日です。

開発中にStrategyとRackミドルウェアを復習したので、軽くまとめてみました。

続きを読む

Rails5で手早くCMS開発をするのに便利なgem7選

エンジニアのタナカです。

4月から新しくサイト開発に携わる方も多いのではないでしょうか?
サイト開発では殆どの場合、CMS機能を用意する必要がありますが、このCMS機能をどう実現するのかというのが最初に検討することだと思います。

CMSといえばWordPressが有名ですが、WordPressも一長一短なので、 様々な理由によりCMSのスクラッチ開発を行う場合も多いと思います。
とはいえスクラッチ開発となると開発コスト等が問題になる場合もあります。 けれども、Railsを以ってすればWordPressと同等以上のCMSを効率よく開発する事も可能です。

ということで、Rails5でのCMS開発に役立つgemを紹介したいと思いますが、 その前にまずはCMSに必要な機能を定義してみます。
CMSと言っても様々なタイプがありますが、今回はニュース・メディア系のCMSを想定しています。

ニュース・メディア系CMSでよくある機能

  • ニュース(ブログ)記事投稿・編集
  • 固定ページ投稿・編集
  • Slug(カスタムURL)の設定
  • 画像投稿
  • タグ付け
  • 予約投稿
  • 履歴管理
  • ユーザー管理

これらの機能を意識しながら、使えそうなgemを紹介いきたいと思います。
これから紹介するgemはいずれも定番のものなので、ぜひ抑えておきたいところです。

ActsAsList

github.com

記事等の並び順を管理することができ、順番の入れ替えが簡単に行えるようになります。
元々Railsに組み込まれていた機能がgemとして切りだされたものですが、Rails5でももちろん使用可能です。

FriendlyId

github.com

たとえばIDが含まれるような以下のようなURLをフレンドリーなURLにしてくれるものです。

http://example.com/states/4323454

このような人間に理解しやすいURLに置き換えることができます。

http://example.com/states/washington

WordPressではslugという機能で提供されています。

Paperclip

github.com

フォームから画像ファイルをアップロードを行う際に便利なgemで、リサイズやサムネイル作成も行ってくれます。
アップロードされた画像をS3に書き出すことも可能なので、画像まわりの処理をこのgemに任せることができます。

ActsAsTaggableOn

github.com

記事などにタグ付けを行えるgemです。 タグの追加削除が簡単に行え、タグでの検索も可能です。

予約投稿

Rails5で利用できるgemは無さそうですが、記事のモデルにpublished_atカラムを追加し、公開日時をセットする方法がよくとられています。
同モデルに以下のようなscopeを定義することで公開済みのものを簡単に取得できるようになります。

scope :published, -> { where("published_at IS NOT NULL").where("published_at <= ?", Time.now) }
scope :draft, -> { where("published_at IS NULL OR published_at > ?", Time.now) }

PaperTrail

github.com

記事の履歴管理に利用できます。
記事を編集した際に、前の状態に戻すといった操作が行えるようになります。

devise

github.com

ユーザー登録やログイン認証といった機能を簡単に組み込むことができます。
アクセス権限を設定することが可能なので、adminユーザーの管理だけでなく、一般ユーザー向けにSNS的な機能を提供したい場合にも利用できます。

Storytime

github.com

これまでに上げたgemの機能を全て実現できるCMS機能が丸ごと入りのgemです。
これらの機能に加え、マルチサイトやナビゲーションの管理など、WordPressとほぼ同等の機能があり、管理画面も付いてきます。

CMSのgemはほかにもいくかリリースされていますが、Rails5対応で多機能なものはStorytime以外に無いと思います。
(固定ページの投稿、編集だけが必要であれば、ComfortableMexicanSofaもお勧めです。)

ただし残念なことに、最近はメンテナンスがあまりされていません。そのため、不具合があった場合は自分で対応することになる可能性が高いです。 (私は自分でメンテすることを前提に利用していますが、Storytimeのソースが読みやすいので問題が発生してもパッチの作成等で対応しています。)

まとめ

gemをうまく組み合わせることでCMSを効率よく開発することができます。(CMSに限った話ではないですが)
また、条件があえば、CMS全部入りのgemを利用することで、開発工数を大幅に削減することも可能です。
WordPressを独自プラグイン等で無理に拡張する前に、Railsでの開発を検討してみてはいかがでしょうか?

CircleCIでRailsのDockerコンテナをECSにデプロイする

nazoです。

Graceful RestartによるRailsアプリのデプロイ を行っていたのですが、もっと手軽に環境ごとデプロイをしたいという需要もあって、Dockerを採用したデプロイも行っています。

CircleCI(1.0)では辛うじてDockerのサポートがありますが、いくつか癖があるので、ECSと含めて運用まで踏まえた手順について紹介したいと思います。

続きを読む

Docker?Vagrant?個人PCのWebアプリケーション開発環境においての環境分離方法

nazoです。

個人PC上では、複数の開発環境が同居することは珍しくありません。その際に、複数のバージョンの同一のソフトウェアが混在することもあります。 それらを切り替える度にアンインストール・インストールを繰り返すのは非効率なので、同居させつつ自動的に切り替わるような状況が最適かと思われます。

これを実現するには様々な方法がありますが、一長一短あるため、具体的にどう違うのか見ていきたいと思います。特にmacOSを中心とした話になります。

続きを読む

Google Spreadsheet のデータを自動で Google Calendar に追加する

おはこんばんちは!! 尾藤 a.k.a. BTO です!!

スギ花粉の脅威に毎日怯えている皆様、ご機嫌いかがでしょうか。 最近は Google Spreadsheet や GAS(Google Apps Script) を使って社内業務の改善などをしております。 だって会社がどんどん大きくなってるから、業務の効率化を進めないと回らないんだもん!!

Google Spreadsheet のデータを Google Calendar に追加したい!!

弊社では営業管理ツールに Salesforce 使っていて、他部署とのデータ連携のために、Salesforce のデータを Google Spreadsheet に同期しています。 ここに動画の公開日の情報があるので、Google Calendar にイベントを追加したいのが今回の目的です。 以前は、全て人が手作業で入力していたため非常にコストのかかる作業だったのが、全て自動でできるようになってので、かなり効率化することができました。

続きを読む

ニューラルネットワーク実装入門

コンピューターが賢くなって、人間がやる仕事が減るといいなと思っているkitabatakeです。 今流行りのニューラルネットワークについて説明したいと思います。

ニューラルネットワークとは

脳神経系をモデルにした情報処理システムで、

文字認識や、音声認識など、コンピュータが苦手とされている処理に対して有効です。

脳の中には多数のニューロン(神経細胞)が存在していて、 各ニューロンは多数の他のニューロンから信号を受け取り、他の多数のニューロンへ信号を受け渡していて、 信号の伝搬によって、様々な情報処理を行っています。

こういった脳内の情報処理の仕組みを真似することで、複雑な情報処理を行おうというものです。

神経細胞の仕組み

神経細胞は下記の画像になっています。

http://www-ailab.elcom.nitech.ac.jp/lecture/neuro/image/neuro.gif

ニューラルネットワーク入門 1.1 神経細胞より参照 http://www-ailab.elcom.nitech.ac.jp/lecture/neuro/neuro1.html

  • 樹状突起 ニューロンへの入力端子

  • 軸索 ニューロンの出力端子

  • シナプス ニューロン間を繋ぐ役割. 軸索から他のニューロンの樹状突起を通して伝達される

入力信号が加わると電位があがりはじめ、 閾値を超えると一時的にニューロンの電位が急激にあがり、シナプスを通じて結合しているニューロンへ出力されます(ニューロンが発火すると表現される)

ニューロンの発火イメージ

http://cdn-ak.f.st-hatena.com/images/fotolife/k/kazoo04/20151117/20151117001033.png

ニューロンの概要とそのモデル より参照 http://kazoo04.hatenablog.com/entry/agi-ac-3

こういったニューロンの仕組みをモデル化すると

http://www-ailab.elcom.nitech.ac.jp/lecture/neuro/image/n_model.gif

ニューラルネットワーク入門 1.2 ニューロンモデルより参照 http://www-ailab.elcom.nitech.ac.jp/lecture/neuro/neuro1.html

ニューロンは入力端子ごとにその入力の重要性を表す結合荷重があり、発火のしやすさを表す閾値を持っていて、 閾値を超えると出力端子から出力信号が出力されるようにモデリングできます。

このニューロンモデルの出力と入力を複雑に連携させて、ネットワーク化することで、複雑な情報処理が可能になります。

階層型ネットワークモデル

ネットワークモデルの1例で、入力層と出力層があり、その間に中間層があります。 ある層のニューロンは前の全てのニューロンからの出力を受け取り、次の層の全てのニューロンに対して出力を行います。

http://ipr20.cs.ehime-u.ac.jp/column/neural/image/layer.gif

画像処理・理解研究室 第5章 ネットワークの形態についてから参照 http://ipr20.cs.ehime-u.ac.jp/column/neural/chapter5.html

実装に入ります

上記で説明したニューロンモデルとネットワークモデルを実装に落とし込んでみたいと思います。

まずは単純パーセプトロン

パーセプトロンとは1957年に考案されたニューロンモデルで、入力層と出力層のみの2層からなるものが単純パーセプトロンと呼ばれます。

https://cdn-ak.f.st-hatena.com/images/fotolife/o/ogidow/20160621/20160621094328.png

rubyで単純パーセプトロンより参照 http://ogidow.hateblo.jp/entry/2016/06/24/184801

各入力ごとに重みと閾値を持ち、入力値 * 重みの総和が閾値を超えると 1 超えないと 0 が出力されます。

重みにマイナスを掛けたものをバイアスと表し、常に入力値が1の入力と考えることで、ニューロンの発火条件をシンプルに表現することができます。

https://qiita-image-store.s3.amazonaws.com/0/115996/5630dd0e-faf1-d800-a073-f2248bf93d4f.png

機械学習ざっくりまとめ~パーセプトロンからディープラーニングまで~ から参照 http://qiita.com/frost_star/items/21de02ce0d77a156f53d

b + x1 * w1 + x2 * w2 が 0以上であれば発火というように表現できるようになります。

ではパーセプトロンでシンプルな回路を実装してみましょう

OR回路とAND回路を考えてみると、OR回路は発火しやすい(どちらかの入力が1であれば発火)もので、 AND回路は発火しにくい(両方の入力が1で発火)ものと考えることができ、そのようにバイアスと重みを設定すると実現できます。

例えば、

  • OR回路: バイアス: -1, 重み1: 2, 重み3

  • AND回路: バイアス: -1, 重み1: 0.5, 重み2: 0.5

と表現できます。

NAND回路はAND回路の設定値を全て正負を反転すると表現できます。

単純パーセプトロンの限界

XOR回路を考えると単純パーセプトロンでは表せないことが解ります。 2つの入力どちらも1の場合に発火しないという条件は表現できません。

そこで多層化

XOR回路は、OR回路とNAND回路をANDにつなげることで表せるので、パーセプトロンを多層化することで表現できます。

http://hokuts.com/wp-content/uploads/2015/12/xor_mlp0.png

高卒でもわかる機械学習 (3) 多層パーセプトロン より参照 http://hokuts.com/2015/12/04/ml3-mlp/

コンピュータはNAND回路の組み合わせでできているということで、パーセプトロンを多層化していくことで、かなり複雑な情報処理が行えると言えると思います。

次に活性化関数

今まで見てきたパーセプトロンでは、バイアス + 入力値 * 重みの総和の入力に対して、1か0を出力するという考えでした。 この入力から出力を生成する関数が活性化関数を呼ばれます。

パーセプトロンのような1か0で出力するものはステップ関数と呼ばれています。

ステップ関数とは別によく使われている活性化関数として、シグモイド関数というものがあります。

https://upload.wikimedia.org/wikipedia/commons/a/ac/Logistic-curve.png

wikipediaより参照 https://ja.wikipedia.org/wiki/%E3%82%B7%E3%82%B0%E3%83%A2%E3%82%A4%E3%83%89%E9%96%A2%E6%95%B0

ステップ関数とは違い、0から1の間の値に収まる形で多様な値が出力されます。 シグモイド関数のこの特性は入力値の細かい調整が出力に反映されるということになるので、バイアス、重みの細かい調整(学習)に都合がいいということで、 一般的にこちらの方が使用されているようです。

シグモイド関数を活性関数に使用したニューロンをシグモイドニューロンと呼ぶことがあるようです。

手書き数字の認識

今までの知識をもとに手書き数字を認識するニューラルネットワークを実装してみたいと思います。

www.oreilly.co.jp

こちらの本が提供している学習データ、コードをベースに見ていきたいと思います。

MNISTとは

MNIST handwritten digit database, Yann LeCun, Corinna Cortes and Chris Burges

MNISTとは6万の手書き数字の学習用画像と、1万のテスト用画像を提供しているサービスで、python用に画像を取得するライブラリも提供されています。 MNISTから取得した学習用画像で学習したデータをもとに、テスト画像の予測の精度を出力するプログラムを見ていきたいと思います。

ネットワークの設計

MNISTの画像は 28px * 28px の画像なので、入力層のニューロンの数としては、784となり、 出力層は各数字の確率なので、0 - 9 までの個数で、10となります。

中間層は2層で、100, 50 とします。 この辺りは学習方法をまだ理解していないので、この設定する意味は理解できていないのですが、結構複雑なニューラルネットワークになっていると思います。

プログラム

配列の計算を簡単に行うために、numpy.array を使用しています。

ゼロから作るDeep Learning で提供されているコードにコメントを追加したものです。

import sys, os, pickle

sys.path.append(os.pardir)
from dataset.mnist import load_mnist
from common.functions import sigmoid, softmax
import numpy as np

# MNISTの学習用データとテスト用データを取得する
def get_data():
  (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, flatten=True, one_hot_label=False)

  # *_trainが学習用のデータで、*_testがテスト用のデータです
  # 今回はテスト用のデータしか使いません
  # x_testがテスト用の画像データで、t_testがテスト用画像に対応した答えの数値です
  return x_test, t_test

# 学習済みのネットワーク(バイアスと重み)のデータを取得する
def init_network():
  with open('sample_weight.pkl', 'rb') as f:
    network = pickle.load(f)

  return network

# ネットワークと入力(画像データ)から数字の予測を行う
def predict(network, x):
  W1, W2, W3 = network['W1'], network['W2'], network['W3']
  b1, b2, b3 = network['b1'], network['b2'], network['b3']

  # 各層の各ニューロンへの入力値の計算(入力 * 重み + バイアス)したものをシグモイド関数に通しています。
  a1 = np.dot(x, W1) + b1
  z1 = sigmoid(a1)
  a2 = np.dot(z1, W2) + b2
  z2 = sigmoid(a2)
  a3 = np.dot(z2, W3) + b3

  # 最終的に出来上がるデータは出力層の長さが10の配列で、keyが対象数字でvalueがその数字である確率が入っています
  return a3

x, t = get_data()
network = init_network()

# 正答率の計算
accuracy_cnt = 0
for i in range(len(x)):
  y = predict(network, x[i])
  p = np.argmax(y) # 確率が一番高いものがニューラルネットワークが予測した数字で、
  if p == t[i]:
    accuracy_cnt += 1 # 予測した数値と提供されている答えが一致していると、正解数をインクリメントします

print("Accuracy:" + str(float(accuracy_cnt) / len(x)))

これを実行すると

Accuracy:0.9352 と出力されます。

MNISTのテスト用画像は人間が見ても判別が難しい画像も含まれているので、結構高い精度が出ていると言えると思います。

次は学習アルゴリズムを勉強したいと思います!