Learning how to learn

I’ve been reading SOFT SKILLS ソフトウェア開発者の人生マニュアル(Japanese version) of “Soft Skills”. I’ve made sense implicitly this method before I read the book.

I found the chapter “Learning how to learn” that is helpful. So I try to introduce the summary of it.

There are ten steps to learn something.

Among step 1 and step 6 are only once steps. Among step 7 and step 10 are repeatedly steps.

Step 1 Get the general picture

You need to know what you do for learning it and find some information for getting the general picture. For example, you want to learn C#; you might find information from the internet, books, blog post, etc.

Step 2 Decide scope

You decide a learning scope in detail in this step. You might have known what you are learning after the previous step. For example, You learn a basic knowledge of C# to create a simple console application.

Step 3 Define goal of achieving learn

It’s important to define a goal before you begin learning.

For example, You have learned how to create a simple console application with C#.

Step 4 Find references

You find various references to learn it from books, blog posts, experts, source code, online documents, etc. You should find many referrences rather than only one reference.

Step 5 Make the learning plan

You should find the shortest path to achieve the goal. Some references explain it too much that you want to know.
You look at the table of contents of references you found, and you find common entries from them. The entries you found might be the path you have to learn.

Step 6 Filter references

To filter references is necessary to step because you cannot read the all books and blog posts.

For example, you check Amazon review and choose high-rated books from there.

Step 7 Learn how to use a minimum of one

You might create a tiny program like a “Hello, world!” and set up a development environment. One of the important things is not to learn too much about it.

Step 8 Play around

Now, you should know a basic knowledge. Just give it a try to create a program! It is important to learn through practice.

Step 9 Learn deep

This step, you might have known a part of them. So go back to references and read the chapter you are learning.

Step 10 Teach someone things you learned

You show other people you learned with a blog post or YouTube, etc.

What is the difference between tf.placeholder and tf.Variable

I read this tutorial. There were the confusing terms they are tf.placeholder and tf.Variable. So I checked the difference point.

tf.placeholder is called when a session runs a calculation.
If once you set a value with tf.placeholder, it can not change an own variable.

tf.Variable can change an own variable by assign method. So tf.Variable is literally “variable.”

Finally, I found this question was beneficial for me.

The top rated answer said:

You use tf.Variable for trainable variables such as weights and biases for your model.

weights = tf.Variable(
    tf.truncated_normal([IMAGE_PIXELS, hidden1_units],
                    stddev=1.0 / math.sqrt(float(IMAGE_PIXELS))), name='weights')

biases = tf.Variable(tf.zeros([hidden1_units]), name='biases')

tf.placeholder is used to feed actual training examples.

images_placeholder = tf.placeholder(tf.float32, shape=(batch_size, IMAGE_PIXELS))
labels_placeholder = tf.placeholder(tf.int32, shape=(batch_size))

for step in xrange(FLAGS.max_steps):
    feed_dict = {
       images_placeholder: images_feed,
       labels_placeholder: labels_feed,
     }
    _, loss_value = sess.run([train_op, loss], feed_dict=feed_dict)

And the another answer said:

The more important difference is their role within TensorFlow. Variables are trained over time, placeholders are are input data that doesn’t change as your model trains (like input images, and class labels for those images).

I appreciate roughly my question thanks to the StackOverflow’s answer.

Index Key Prefix Length Limitation on InnoDB

Index Key Prefix Length Limitation on InnoDB

I encountered the problem index key prefix length limitation on InnoDB when I migrate a database. The problem was like this:

Specified key was too long; max key length is 767 bytes

The index key prefix length limit is 767 bytes if you use the version of MySQL either 5.5 or 5.6. Or you use 5.7 the default is 3076 bytes.

innodb_large_prefix is deprecated and will be removed in a future release. Therefore, We need to consider whether we should enable innodb_large_prefix.

And Index key prefixes larger than 767 bytes are silently truncated if you change innodb_large_prefix to OFF from ON.

I went to builderscon tokyo 2017

I went to builderscon tokyo 2017 from August 3rd to 5th.

The eve of the conference

I heard some fascinating talks, but I was told not to tell anyone about them, so unfortunately I can’t write about them.

I think the organizers should keep this event next time.

Day 1

Recognizing Japanese idols with Deep Learning

@sugyan spoke about recognizing Japanese idols with Deep Learning.It helped me to learn about Deep Learning recognizes images.

He gave me some hints on image recognition. Thank you @sugyan.

Building high performance push notification server in Go

@cubicdaiya[https://twitter.com/cubicdaiya] spoke abount a push notification server.

Gaurun might be able to use my project. I’ll look up detailed information about it.

After party

I went to the after party, which was held after the end the day 1. Almost all of the dishes were delicious.

Day 2

Factory Class

Jesse Vincent told me the exciting episode that’s about developing keyboards from scratch.

He said it’s important to meet up with a supplier and keep a good relationship with them if you want to make a good product in China.

Finally

The name card the organizers made was useful for me, and I think the voting system (It uses a QR code) to choose best speakers was convenient for us.

There was only one thing I was dissatisfaction at the lunch session. I think that I and the other audience members were crammed into there, so I think the room was a little small.

But I had a totally enjoyable time at the conference, and I would love to go again!

How to make development environment of Go with Mono and Protocol Buffers

I joined a project, and I begin to develop an application in it. This project has used golang. So I studied it and prepared its developing environment.

This article is the what I did to make development environment of GO.

Prerequisite

What our golang project needs.

Glide

Glide manage a project dependency.

What is the difference between “go get” and “Glide”

As far as I searched, “go get” just installs a package into your local directory, and solves library dependencies. By contrast, “Glide” is package manager sort of npm. It uses a file defined depending packages.

Fresh

Fresh is an auto-reloader for a web application. When you change a file of golang or template, Fresh reload (recompile) the file automatically, and apply the web application.

Goose

Goose is a migration tool.

Provision

Add provisioning config

We’ll provision from a shell script file.

Vagrantfile

Vagrant.configure("2") do |config|
  ...
  config.vm.provision :shell, path: "bootstrap.sh"
  ...
end

Environment variable golang uses

Golang uses GOROOT and GOPATH environment variables.

To installing a custom location use the GOROOT. If you don’t want change one, you don’t need to set this environment variable.

The GOPATH is used to specify directories for a golang project.

Install Go

Install Go and set GOROOT, GOPATH and PATH.

Install go and set environment variables for go

apt-get update
apt-get -y install curl git
wget https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
tar -xvf go1.8.3.linux-amd64.tar.gz
mv go /usr/local

export GOROOT=/usr/local/go
export GOPATH=/vagrant/go
mkdir -p $GOPATH/bin
export PATH=$PATH:$GOPATH/bin:$GOROOT/bin
source ~/.bashrc

And You should add commands because GOROOT, GOPATH and PATH I set in bootstrap.sh doesn’t influence the vagrant environment.

The environment variables for golang in the vagrant environment

echo 'export GOROOT=/usr/local/go' >> /home/vagrant/.bashrc
echo 'export GOPATH=/vagrant/go' >> /home/vagrant/.bashrc
echo 'export PATH=$PATH:$GOPATH/bin:$GOROOT/bin' >> /home/vagrant/.bashrc

I install Glide.

Install Glide

curl https://glide.sh/get | sh

In the vagrant environment

Solve library dependency with Glide

It’s simple; you just execute above command.

Install glide

$ glide install

And install Fresh and Goose by go get.

Install Fresh and Goose

$ go get github.com/pilu/fresh
$ go get bitbucket.org/liamstask/goose/cmd/goose

Install protobuf

I referred to this article.

Install protobuf

$ curl -OL  https://github.com/google/protobuf/releases/download/v3.3.0/protoc-3.3.0-linux-x86_64.zip
$ unzip protoc-3.3.0-linux-x86_64.zip -d protoc3
$ sudo mv protoc3/bin/* /usr/local/bin/
$ sudo mv protoc3/include/* /usr/local/include/

Install Mono

I had to install an old version of Mono for the project reason. So I install it from tar ball.

This article is useful for me.

Install Mono

$ sudo apt-get install g++ gettext make
$ http://download.mono-project.com/sources/mono/mono-2.11.4.tar.bz2
$ tar xvjf mono-2.11.4.tar.bz2
$ cd mono-2.11.4
./configure --prefix=/opt/mono-2.11

$ make
$ make install

ln -s /opt/mono-2.11/bin/mono /usr/bin/mono
ln -s /opt/mono-2.11/bin/gmcs /usr/bin/gmcs

How to change Timezone on Docker with Ubuntu 16.04

Ubuntu 16.04 and every other use UTC by default.

I want to change to JST. So I search about this on the web, and some site said to use like this.

Show list of time zone

$ timedatectl list-timezones

But I executed this command, and then above message occurs.

Error about bus happen

$ timedatectl list-timezones
Failed to create bus connection: No such file or directory

It is a problem to use systemd. Ubuntu has used systemd since 16.04.

To use systemd on docker container is pretty tough. So I used tzdata. It is still available to install via apt on Ubuntu 16.04, but if you can also change time zone with systemd. See this document.

I write this config in Dockerfile like this. And build the container.

Dockerfile

FROM ubuntu:16.04

RUN \
  apt-get -y install tzdata && \
  ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

Then I enter the container and check time zone.

root@4dbd2aff2747:~# cat /etc/timezone
Asia/Tokyo

root@9dce4012502e:~# strings /etc/localtime
TZif2
JCST
TZif2
JCST
JST-9

The docker container’s time zone becomes JST!

Immutable.jsのList.merge()とList.concat()の挙動の違い

Immutable.jsのListmerge()Listを結合できると思っていたら違った。

const a = Immutable.List([
    {item_name: 'apple'},
    {item_name: 'chicken'}
])

const b = Immutable.List([
    {item_name: 'car'}
])

こんな感じでリストがあって結合したいと思ったとき、ドキュメントを読むとmerge()でできそう。

しかしmerge()ではできません。concat()を使います。

merge()concat()を比べてみます。

console.log(a.merge(b).toJS())

// Console
// [Object {
//   item_name: "car"
// }, Object {
//   item_name: "chicken"
// }]

// This is what I want to do
console.log(a.concat(b).toJS())

// Console
// [Object {
//   item_name: "apple"
// }, Object {
//   item_name: "chicken"
// }, Object {
//   item_name: "car"
// }]

merge()は配列のインデックスを元に merge しています。{item_name: 'apple'}a[0]です。{item_name: 'car'}b[0]と同じインデックスであるため、マージされてしまいます。

concat()は素直にaのListにbのListを連結していることがわかります。

List.merge()の挙動について少し勘違いをしてました。

Play Framework 2.5の設定ファイルの書き方

すでにPlay Framework 2.6が公開されていますが、Play Framework 2.5の設定方法について少しまとめておきます。

Play Frameworkの設定はデフォルトではapplication.confに書くようになっています。

application.confには何を書くか

DBやAkkaアクター、ログや自分で定義したい設定など、基本的に全ての設定を書きます。

application.confのロード

デフォルトでは classpath にある reference.conf がロードされます。Play Frameworkではデフォルトのセッティングとして reference.conf が定義されているのですが、 application.conf を記述することで任意の設定に上書きすることができます。

application.conf はJavaのシステムプロパティで上書きすることもできます。-Dhttp.port=1234のような感じにします。
また application.conf の設定ファイル自体を置き換えることもできます。システムプロパティにconfig.resourcedevelopment.confのように指定します。

application.confのフォーマット

Play Frameworkでは application.confHOCONと呼ばれるフォーマットで設定ファイルを記述します。
HOCONはJSONに似たフォーマットです。

sbt runで開発環境の設定をする

開発用にrunコマンドでアプリケーションを起動するとき build.sbt に設定を追加することができます。
PlayKeys.devSettings := Seq("play.server.http.port" -> "8080")のように設定します。
この設定はアプリケーションをデプロイするときには有効になりません。

runコマンドではアプリケーションがコンパイルされる前にHTTP serverが起動します。そのためHTTP serverが起動した段階では application.conf からHTTP serverの設定を読み込むことはできません。HTTP serverを設定するにはシステムプロパティを使用するかdevSettingsを設定する必要があります。

HOCONシンタックス

HOCONはJSONに似ていますが、違う点について説明します。

同じ部分

  • UTF-8を使う
  • クオートしたstring
  • string, number, object, array, boolean, null

コメント

//#を使用します。

ルートのブレース

JSONではルートでobject({})かarray([])である必要がありますが、HOCONではルートでこれらの括弧は使用しません。

key-valueの区切り

:の他に=でもkey-valueを区切ることができます。
また、"foo": {}"foo" {}のように書くことができます。

複数のkeyでパスを表現する

foo.bar : 42foo { bar : 42 }と同じ意味です。

a.x : 42, a.y : 43a { x : 42, y: 43 }と同じ意味です。

代入

${?foo}${foo}のようにすることでキーがfooの値を代入することができます。また代入するキーはルートからの絶対パスで指定する必要があります。

インクルード

他のファイルから設定を追加でインクルードすることができます。インクルードするファイルはオブジェクトである必要があります。
同じキーがあった場合は一番最後に評価(パース)された値に置き換えられます。

開発環境と本番環境のように環境別にDBの接続先などを変えたいときがあります。そのほかの設定が共通の場合、以下のように書くことができます。

base.conf

akka {
  ...
}

development.conf

include "base.conf"

# DB configs

development.conf から base.conf をインクルードすることで共通のAkkaの設定を追加することができます。

設定方法の一部を紹介しましたが、ここに書かれている内容はこちらに詳しく書かれています。

Docker Swarm modeでservice間のアクセスを可能にする

Docker Swarmのservice間で名前解決して互いにネットワークアクセスできるように設定する方法です。

使用したDocker engineのバージョンは 1.13.0 です。

service discoveryを使用する

service discovery を使用するとservice名で名前解決できるようになります。例えば appdb という2つのserviceを作成した時、app から jdbc:mysql://db:3306/mydatabase のように db に接続できるようになります。このように名前解決できる機能のことを service discovery と言います。

service discoveryは、例えばWebアプリケーションでHTTPSを使いため、WebアプリケーションのserviceとNginxのserviceを立ち上げて、Nginxをリバースプロキシとして使いたい場合を考えてみます。

Webアプリケーションのservice名は myapp、 Nginxのservice名は proxy とします。
Webアプリケーションはport 9000で動作していて、Nginxは外部のHTTPSのport 443を受け取ってport 9000にリバースプロキシします。

myapp(9000) <- (9000)proxy(443) <- Webブラウザ

この時Nginxをリバースプロキシとして使いたいので、以下のような設定をします。

upstream my-backend {
  server myapp:9000;
}

server myapp:9000の部分でmyappのポート9000に対してリクエストを転送していることがわかります。

このservice discoveryを使用するには、新規にoverray networkを作成する必要があります。
Attach services to an overlay network

overlay networkを作成する

以下はoverlay networkを作成する例です。

$ docker network create --driver overlay my-network

次にこのネットワークを追加したserviceを作成します。
以下はNginxと自分で作成したアプリケーションのserviceを作成しています。

Nginx

$ docker service create --replicas 1 -p 80:80 --name nginx --network my-network my-nginx

Myapp

$ docker service create --replicas 1 --name app --network my-network my-app

このように同じoverlay networkを設定してserviceを作成します。同じネットワークに存在するserviceはVIPとDNSが設定されて、service名に名前解決できるようになります。

By default, when you create a service attached to a network, the swarm assigns the service a VIP. The VIP maps to a DNS alias based upon the service name. Containers on the network share DNS mappings for the service via gossip so any container on the network can access the service via its service name.

Use swarm mode service discovery

実際に app serviceで作成したコンテナに入ってdig nginxなどすると名前解決されていることがわかります。

service discoveryのハマりどころ

動作に必要なポートが開いているか確認する

service discoveryを使用するにはPort 7946 TCP/UDP とPort 4789 UDP が開いていることが必要です。
もし同じoverlay networkを設定しているのに名前解決できない場合は、netstat -antupしてみます。上記のポートが見つからなければdocker daemonをrestartしてみると直ることがあります。
このportがlistenされない原因を調べてみましたが、結局よくわかりませんでした。新しいバージョンだと解決されているかもしれません。
このportがlistensされていなくてもDocker Swarmは警告を出さない(たぶん)ので気づきにくいです。

また、portは問題ないのにうまくservice discoveryできない場合はホストマシン間のportが拒否されていないか確認します。もしES2のようなserviceを使用している場合は、そちらのポートの設定も確認します。

serviceを起動する順番

serviceに依存している別のserviceを立ち上げる場合、立ち上げる順番に気をつける必要があります。

先の例だと、myapp を立ち上げる前に proxy を立ち上げてしまうと、myapp がまだservice discoveryに登録されていないので、 proxy service起動時に名前解決されずにエラーで起動できません。先に myapp serivceを立ち上げてから proxy serviceを立ち上げる必要があります。

このようにservice名に依存したserviceがある場合は、serviceを立ち上げる順番に気をつける必要があります。

また、Nginxの場合だとservice名を変数にして、service discoveryのDNSで名前解決する方法があります。この時resolver 127.0.0.11 valid=2s;でDNSのTTLに関わらず、2秒で更新するようにします。

serviceを起動する順番に依存しないようにする

resolver 127.0.0.11 valid=2s;
set $upstream "myapp";

upstream my-backend {
  server myapp:9000;
}

HTTPを使ったDocker Registryを作る

基本的にドキュメントに書いてありまが、Docker RegistryでHTTPを使おうとすると少し面倒だったので、まとめておきます。

プライベートなネットワークで使っているぶんにはHTTPで十分ですが、いくつか設定を追加する必要があります。

Docker Registryを起動する

Docker Registryを起動すにはDeploy a registry serverに書かれている通り、以下のコマンドを実行します。
Docker Registryはこれで終わりです。

$ docker run -d -p 5000:5000 --restart=always --name registry registry:2

Docker Registryに接続するクライアントの設定

こちらに書かれている通り以下のようにDockerの設定を追加します。

Docker Registry が10.0.0.2:5000でLISTENしている例です。

/etc/docker/daemon.json

{ "insecure-registries":["10.0.0.2:5000"] }

/etc/default/docker

DOCKER_OPTS="--insecure-registry 10.0.0.2:5000"

設定はこの2つです。

あとはDocker daemonをrestartします。

# systemdの場合
$ sudo systemctl restart docker.service

これでHTTPで接続できるようになります。

設定は簡単ですが、公式ドキュメントから設定方法を見つけられなかったので、設定に少し時間がかかりました。