- 投稿日:2019-10-08T17:58:05+09:00
Flaskでツイート自動生成プログラム作ってみた
動機
LSTMで文書の自動生成を行う簡易なWebアプリを作成しました。
業務で自然言語処理を行うっていますが、趣味で何か目に見える楽しいものを作りたいなと考え作成に至りました。1. 環境
- Docker
- Python3.6
- Flask
- PyTorch
githubレポジトリはこちら
2. Dockerfile
DockerfileFROM ubuntu:16.04 RUN apt-get update \ && apt-get install -y mecab \ && apt-get install -y libmecab-dev \ && apt-get install -y mecab-ipadic-utf8\ && apt-get install -y git\ && apt-get install -y make\ && apt-get install -y curl\ && apt-get install -y xz-utils\ && apt-get install -y file\ && apt-get install -y sudo\ && apt-get install -y wget RUN git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git\ && cd mecab-ipadic-neologd\ && bin/install-mecab-ipadic-neologd -n -y RUN apt-get install -y software-properties-common vim RUN add-apt-repository ppa:jonathonf/python-3.6 RUN apt-get update RUN apt-get install -y build-essential python3.6 python3.6-dev python3-pip python3.6-venv RUN python3.6 -m pip install pip --upgrade RUN pip install flask RUN pip install numpy RUN pip install pandas RUN pip install sklearn RUN pip install gensim RUN pip install mecab-python3 RUN pip install cloudpickle RUN pip install torch RUN export LC_ALL=C.UTF-8 RUN export LANG=C.UTF-8 EXPOSE 5000MeCab Neologd, その他必要なライブラリのインストールやFlaskに必要な環境変数の設定、ポート開放など行っています。
$cd path/to/directory $docker build -t flask-app:1.0 .Dockerコンテナを起動する際の注意はポートを5000で開放することです。Flaskのデフォルト開放ポートが5000のためホストとコンテナで5000ポートを接続しました。
$docker run -it -p 5000:5000 -v path/to/directory:/flask-app flask-app:1.0Dockerコンテナの起動を完了しました。
3. FlaskでWebアプリ作成
app.pyimport cloudpickle import torch import LSTM_model from flask import Flask, render_template, request app=Flask(__name__) app.debug = True @app.route("/", methods=["GET"]) def index(): return render_template("index.html", message="最初のメッセージを入力してね!") @app.route("/", methods=["POST"]) def form(): with open('data/model.pkl', 'rb') as f: model = cloudpickle.load(f) field=request.form["field"] maked_words = LSTM_model.generate_seq(model, start_phase=field, length=20) return render_template("index.html", message=maked_words) if __name__ == '__main__': app.run(host='0.0.0.0')GET, POSTで入力した文章を推論、出力を行なっています。
私がハマったポイントとしてはVMでのポート開放です。app.run(host='0.0.0.0')ここでhost="0.0.0.0"としておかないとアクセスできずにハマるためご注意を(あまりFlaskの仕様に慣れていませんでした)
index.html<!doctype html> <html lang="ja"> <head> <title>tweet_maker</title> <meta charset='utf-8'> </head> <body> <h1>tweet_maker</h1> <p>{{message}}</p> <div> <form method="post" action="/"> <input type="text" name="field"> <input type="submit"> </form> </div> </body> </html>LSTM_model.pyimport re import pickle import torch import torch.nn as nn import MeCab class SequenceGenerationNet(nn.Module): def __init__(self, num_embeddings, embedding_dim=50, hidden_size=50, num_layers=1, dropout=0.2): super().__init__() self.emb=nn.Embedding(num_embeddings, embedding_dim) self.lstm=nn.LSTM(embedding_dim, hidden_size, num_layers, batch_first=True, dropout=dropout) self.linear=nn.Linear(hidden_size, num_embeddings) def forward(self, x, h0=None): x=self.emb(x) x, h =self.lstm(x, h0) x=self.linear(x) return x, h def make_wakati(sentence): tagger = MeCab.Tagger("-Owakati -d /usr/lib/mecab/dic/mecab-ipadic-neologd") sentence = sentence.replace(",\n", " ") # MeCabで分かち書き sentence = tagger.parse(sentence) # 半角全角英数字除去 sentence = re.sub(r'[0-90-9]+', "0", sentence) sentence.translate(str.maketrans({chr(0xFF01 + i): chr(0x21 + i) for i in range(94)})) # 記号もろもろ除去 sentence = re.sub(r'[\._-―─!@#$%^&\-‐|\\*\“()_■×+α※÷⇒—●★☆〇◎◆▼◇△□(:〜~+=)/*&^%$#@!~`){}[]…\[\]\"\'\”\’:;<>?<>〔〕〈〉?、。・,\./『』【】「」→←○《》≪≫\n\u3000]+', "", sentence) # スペースで区切って形態素の配列へ wakati = sentence.split(" ") # 空の要素は削除 wakati = list(filter(("").__ne__, wakati)) return wakati def sentence2index(sentences): wakati = make_wakati(sentences) with open("data/w2i.pkl", "rb")as data: word2index = pickle.load(data) id_stc = [word2index[i] for i in make_wakati(sentences)] return id_stc def generate_seq(net, start_phase="私は", length=200, temperature=0.8, device="cpu"): net.eval() result=[] start_tensor=torch.tensor( sentence2index(start_phase), dtype=torch.int64 ).to(device) x0=start_tensor.unsqueeze(0) o, h=net(x0) out_dist=o[:, -1].view(-1).exp() top_i=torch.multinomial(out_dist, 1)[0] result.append(top_i) for i in range(length): inp=torch.tensor([[top_i]], dtype=torch.int64) inp=inp.to(device) o, h=net(inp, h) out_dist=o.view(-1).exp() top_i=torch.multinomial(out_dist, 1)[0] result.append(top_i) with open("data/i2w.pkl", "rb")as data: index2word = pickle.load(data) res = "".join([index2word[int(i.to("cpu").numpy())] for i in result]) return start_phase+ resLSTMの推論はこちらで行なっています。学習データはgithubにアップしているためそちらを参照ください。コード中のi2wは単語とインデックスの関係を表すpickleファイルです。
4. 動かしてみる
flask run --host 0.0.0.0
上記コードを入力後のURLにアクセスすると動作します。
実際の画面はこんな感じです。興味ある方は是非git cloneして遊んで見てください。参考にさせていただいた記事
こちらの記事を参考にさせていただきました。
https://qiita.com/oreyutarover/items/909d614ca3b48d2c9e16
- 投稿日:2019-10-08T17:58:05+09:00
Flaskでツイート自動生成Webアプリ作ってみた
動機
LSTMで文書の自動生成を行う簡易なWebアプリを作成しました。
業務で自然言語処理を行うっていますが、趣味で何か目に見える楽しいものを作りたいなと考え作成に至りました。1. 環境
- Docker
- Python3.6
- Flask
- PyTorch
githubレポジトリはこちら
2. Dockerfile
DockerfileFROM ubuntu:16.04 RUN apt-get update \ && apt-get install -y mecab \ && apt-get install -y libmecab-dev \ && apt-get install -y mecab-ipadic-utf8\ && apt-get install -y git\ && apt-get install -y make\ && apt-get install -y curl\ && apt-get install -y xz-utils\ && apt-get install -y file\ && apt-get install -y sudo\ && apt-get install -y wget RUN git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git\ && cd mecab-ipadic-neologd\ && bin/install-mecab-ipadic-neologd -n -y RUN apt-get install -y software-properties-common vim RUN add-apt-repository ppa:jonathonf/python-3.6 RUN apt-get update RUN apt-get install -y build-essential python3.6 python3.6-dev python3-pip python3.6-venv RUN python3.6 -m pip install pip --upgrade RUN pip install flask RUN pip install numpy RUN pip install pandas RUN pip install sklearn RUN pip install gensim RUN pip install mecab-python3 RUN pip install cloudpickle RUN pip install torch RUN export LC_ALL=C.UTF-8 RUN export LANG=C.UTF-8 EXPOSE 5000MeCab Neologd, その他必要なライブラリのインストールやFlaskに必要な環境変数の設定、ポート開放など行っています。
$cd path/to/directory $docker build -t flask-app:1.0 .Dockerコンテナを起動する際の注意はポートを5000で開放することです。Flaskのデフォルト開放ポートが5000のためホストとコンテナで5000ポートを接続しました。
$docker run -it -p 5000:5000 -v path/to/directory:/flask-app flask-app:1.0Dockerコンテナの起動を完了しました。
3. FlaskでWebアプリ作成
app.pyimport cloudpickle import torch import LSTM_model from flask import Flask, render_template, request app=Flask(__name__) app.debug = True @app.route("/", methods=["GET"]) def index(): return render_template("index.html", message="最初のメッセージを入力してね!") @app.route("/", methods=["POST"]) def form(): with open('data/model.pkl', 'rb') as f: model = cloudpickle.load(f) field=request.form["field"] maked_words = LSTM_model.generate_seq(model, start_phase=field, length=20) return render_template("index.html", message=maked_words) if __name__ == '__main__': app.run(host='0.0.0.0')GET, POSTで入力した文章を推論、出力を行なっています。
私がハマったポイントとしてはVMでのポート開放です。app.run(host='0.0.0.0')ここでhost="0.0.0.0"としておかないとアクセスできずにハマるためご注意を(あまりFlaskの仕様に慣れていませんでした)
index.html<!doctype html> <html lang="ja"> <head> <title>tweet_maker</title> <meta charset='utf-8'> </head> <body> <h1>tweet_maker</h1> <p>{{message}}</p> <div> <form method="post" action="/"> <input type="text" name="field"> <input type="submit"> </form> </div> </body> </html>LSTM_model.pyimport re import pickle import torch import torch.nn as nn import MeCab class SequenceGenerationNet(nn.Module): def __init__(self, num_embeddings, embedding_dim=50, hidden_size=50, num_layers=1, dropout=0.2): super().__init__() self.emb=nn.Embedding(num_embeddings, embedding_dim) self.lstm=nn.LSTM(embedding_dim, hidden_size, num_layers, batch_first=True, dropout=dropout) self.linear=nn.Linear(hidden_size, num_embeddings) def forward(self, x, h0=None): x=self.emb(x) x, h =self.lstm(x, h0) x=self.linear(x) return x, h def make_wakati(sentence): tagger = MeCab.Tagger("-Owakati -d /usr/lib/mecab/dic/mecab-ipadic-neologd") sentence = sentence.replace(",\n", " ") # MeCabで分かち書き sentence = tagger.parse(sentence) # 半角全角英数字除去 sentence = re.sub(r'[0-90-9]+', "0", sentence) sentence.translate(str.maketrans({chr(0xFF01 + i): chr(0x21 + i) for i in range(94)})) # 記号もろもろ除去 sentence = re.sub(r'[\._-―─!@#$%^&\-‐|\\*\“()_■×+α※÷⇒—●★☆〇◎◆▼◇△□(:〜~+=)/*&^%$#@!~`){}[]…\[\]\"\'\”\’:;<>?<>〔〕〈〉?、。・,\./『』【】「」→←○《》≪≫\n\u3000]+', "", sentence) # スペースで区切って形態素の配列へ wakati = sentence.split(" ") # 空の要素は削除 wakati = list(filter(("").__ne__, wakati)) return wakati def sentence2index(sentences): wakati = make_wakati(sentences) with open("data/w2i.pkl", "rb")as data: word2index = pickle.load(data) id_stc = [word2index[i] for i in make_wakati(sentences)] return id_stc def generate_seq(net, start_phase="私は", length=200, temperature=0.8, device="cpu"): net.eval() result=[] start_tensor=torch.tensor( sentence2index(start_phase), dtype=torch.int64 ).to(device) x0=start_tensor.unsqueeze(0) o, h=net(x0) out_dist=o[:, -1].view(-1).exp() top_i=torch.multinomial(out_dist, 1)[0] result.append(top_i) for i in range(length): inp=torch.tensor([[top_i]], dtype=torch.int64) inp=inp.to(device) o, h=net(inp, h) out_dist=o.view(-1).exp() top_i=torch.multinomial(out_dist, 1)[0] result.append(top_i) with open("data/i2w.pkl", "rb")as data: index2word = pickle.load(data) res = "".join([index2word[int(i.to("cpu").numpy())] for i in result]) return start_phase+ resLSTMの推論はこちらで行なっています。学習データはgithubにアップしているためそちらを参照ください。コード中のi2wは単語とインデックスの関係を表すpickleファイルです。
4. 動かしてみる
flask run --host 0.0.0.0
上記コードを入力後のURLにアクセスすると動作します。
実際の画面はこんな感じです。興味ある方は是非git cloneして遊んで見てください。参考にさせていただいた記事
こちらの記事を参考にさせていただきました。
https://qiita.com/oreyutarover/items/909d614ca3b48d2c9e16
- 投稿日:2019-10-08T17:04:39+09:00
dockerでkotlinをcliでコンパイル、javaで実行できる環境をつくった
はじめてkotlinを勉強しようと思ったのですが、macにkotlinコンパイラをいれるのも少し嫌だったので、docker composeで一式つくりました。
ビルドツールを使用することは想定しておらず、kotlinの簡単な文法を動かしながら確認できる環境を用意するというコンセプトのもと作成してます。
必要な方は参考にしてみてください。できたもの
./docker-compose.yml
version: "3.7" services: java: build: ./docker/java tty: true volumes: - ./src:/usr/local/src./docker/java/Dockerfile
FROM openjdk:13-slim RUN apt-get update && apt-get install -y git \ unzip \ zip \ curl \ vim WORKDIR /usr/local/src RUN curl -s https://get.sdkman.io | bash RUN /bin/bash -l -c "chmod a+x $HOME/.sdkman/bin/sdkman-init.sh;$HOME/.sdkman/bin/sdkman-init.sh;sdk install kotlin" CMD ["/bin/bash"]ディレクトリ構成は以下のようになってます
. ├── docker │ └── java │ └── Dockerfile ├── docker-compose.yml └── src └── test.ktつかいかた
下準備
docker-compose.ymlを配置したディレクトリで、以下のコマンドを実行するのみです。
$ docker-compose build $ docker-compose upうごかす
実際に、
test.kt
をコンパイルして、java
コマンドで実行します。
コンパイルする対象は./src/test.kt
です。fun main(args: Array<String>) { println("Hello, World!") }コンテナに入って、コンパイルして、実行します。
$ docker-compose exec java bash root@3b62768acd0b:/usr/local/src# kotlinc test.kt -include-runtime -d test.jar OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release. root@3b62768acd0b:/usr/local/src# java -jar test.jar Hello, World! root@3b62768acd0b:/usr/local/src#
-Xverify:none
は駄目だというwarningがでてしまいますが、コンパイルができて、javaコマンドで実行することができました。さらに、
/usr/local/src
をボリュームマウントしてますので、コンパイル後にできたjarファイルは、ホストマシンのファイルシステムでも確認可能です。. ├── docker │ └── java │ └── Dockerfile ├── docker-compose.yml └── src ├── test.jar └── test.ktさいごに
これから勉強を進めていく中で、ビルドツール使いたくなったり、いろいろ不都合がでてくるかもしれませんが、一旦環境が整ったということで、どんどん勉強していきたいです!
- 投稿日:2019-10-08T16:04:04+09:00
Docker CentOSイメージを使用してPHP-FPMを実行する
CentOSイメージをベースにしてphp-fpmが動作するコンテナを作成します。サンプルです。
リポジトリ
https://github.com/kakizaki/sample_docker_phpfpm_cent動機
DockerHubにはphp-fpmのための公式のイメージがありますが、ベースは
debian
またはalpine
だったと思います。
実際のサーバー環境はCentOSを使用していて、yumによりパッケージをインストールをしています。
コンテナでもyumが使えて、同じように書けると楽です。使用手順
docker-compose up
を実行すると、nginxコンテナとphp_fpmコンテナが起動します。
ブラウザでhttp://localhost/index.php
を表示すると、phpinfoの実行結果が表示されると思います。はまった点
php-fpmの設定を誤っていたことで、nginxコンテナからphp_fpmコンテナへアクセスできずに、はまってしまいました。
(unixソケットを使用する場合には不要ですが)php/www.conf; List of addresses (IPv4/IPv6) of FastCGI clients which are allowed to connect. ; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original ; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address ; must be separated by a comma. If this value is left blank, connections will be ; accepted from any ip address. ; Default Value: any ; HACK 外部からのアクセスを許す場合はコメント(any)にするか、IPを指定する ;listen.allowed_clients = 127.0.0.1
- 投稿日:2019-10-08T15:07:08+09:00
docker-compose up -d を実行したらport is already allocatedのエラーが表示されたときの対処法
状況
docker-compose up -d
を実行すると以下のエラーが発生。
どうやら3306は既に割り当てているものがあるらしい。ERROR: for qiita_clone_database_1 Cannot start service database: driver failed programming external connectivity on endpoint qiita_clone_database_1 (36532cbe7d470eac9dce4a34198da5ebc15cd86aae371e98c9fb2d0272b6eeb9): Bind for 0.0.0.0:3306 failed: port is already allocated対処法
sudo lsof -i:ポート番号
で指定したポートを使用しているプロセスを確認することができる。
sudo lsof -i:3306
で以下のログが表示される。COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME com.docke 1372 khiro 15u IPv6 0x68b93b7c3d446421 0t0 TCP *:mysql (LISTEN)COMMANDの下にあるcom.dockeが実行しているプロセス名。
PIDの1372がプロセス番号を指す。
sudo kill プロセス番号
で指定したプロセス番号を削除できるので,今回はsudo kill 1372
を実行。その後、再度
docker-compose up -d
を実行して以下のような表示がでれば完了。Creating qiita_clone_database_1 ... done
- 投稿日:2019-10-08T10:47:49+09:00
【AWS】Growi構築でコケたところ
今回は、仕様でwikiが必要になり、Growiという和製wikiに目をつけた。
この参考サイトを参考にして、AWS上にEC2をたて、その中にドッカーを構築。ドッカー内にGrowiを構築する。
参考サイトにあるコマンドに1つだけ、コマンドを追加する。
※EC2の初期設定で、パッケージの最新化を行うyum updateを実行する。コマンドリストは以下
sudo su - yum update yum install -y docker docker -v curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose docker-compose -v systemctl enable docker groupadd docker gpasswd -a $USER docker systemctl restart docker exit sudo su - yum install -y git cd /home/ec2-user git clone https://github.com/weseek/growi-docker-compose.git growi cd /home/ec2-user/growi vi docker-compose.yml docker-compose up -dここでこけました。
vi docker-compose.yml
参考サイトでは、ポートの変更に言及していますが、
ポートの変更とパスワードシードを変更しないと、ドッカーの起動時に失敗しました。また、今回、最初はケチって、t2.microで実行しましたが、
スペックが足りず、t3.smallで実行しないと起動できないことがわかりました。
※気づくのになかなか苦労してしまいました。
- 投稿日:2019-10-08T10:46:25+09:00
Debug timezone in Docker
- Code
package main import ( "fmt" "github.com/uniplaces/carbon" ) func main() { loc := "Asia/Tokyo" now, _ := carbon.NowInLocation(loc) today := now.StartOfDay() tomorrow := today.AddDay() fmt.Println(now, today, tomorrow) }$ docker run --rm -it --privileged -v $(pwd):/app golang bash $ cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime $ date +%T -s "07:00:00"
- 投稿日:2019-10-08T01:38:44+09:00
dockerで環境構築しているPCでVagrantの環境構築は厳しい?
タイトルの通りなんですけど・・・・・・
実はDockerで環境構築しているPCにVagrantでVagrant upができなかったお話。
ことの発端は
Vagrantで環境構築→別件でDockerでコンテナを開始しました。
(その時もなんかエラーが出て何だかんだしててで解決しました)後日、PCでVagrant up後、下記のエラーが発生↓
調べてみると解決策は出てきます。Hyper-Vを無効にしなければいけないみたいですね。
https://qiita.com/masoo/items/b73dadb0e99f9be528fe
https://qiita.com/koji9004/items/662eab6617de3533d190どこを調べても、これ以外の方法が・・・・・
Docker使うのにHyper-V使うので、毎回Hyper-Vを有効・無効にする度に
再起動するのはちとめんどい・・・・・そんな感じのどーでもいい記事でした。
※ちなみに、Hyper-V無効後に有効にしたらDockerのMySqlのデータ吹っ飛びました。
- 投稿日:2019-10-08T00:58:54+09:00
Spring Boot + Docker + Github での環境構築 クイックスタート
Spring Bootのアプリ作成
1. Spring InitilizarでHelloWorldのアプリ作成
以下のリンクをクリックして、Generateでダウンロード
2. HelloWorldのコントローラーを作成
HelloWorldを表示するアプリ作成。
HelloWorld.java@RestController public class HelloWorld { @RequestMapping("/") public String helloWorld() { return "hello world"; } }以下のURLをクリックすると、ローカル環境にアクセスできることを確認
3. Githubにデータをプッシュする
上記の作成したモジュールをGitに追加する
https://github.com/harutotanabe09/SpringBootHelloWorld
4. Dockerファイルを用意する
・ できるだけ軽量コンテナを使用する(alpineを使用する)
・ コンテナ内でのGradleのインストールは不要
・ gradlew bootRunでコンパイルから実行まで実施するDokcerfileFROM openjdk:8-alpine RUN apk update && \ apk upgrade && \ apk add --no-cache \ bash \ curl-dev \ ruby-dev \ build-base \ git RUN mkdir /usr/app WORKDIR /usr/app # アプリケーションをダウンロード RUN git clone https://github.com/harutotanabe09/SpringBootHelloWorld.git . # アプリケーションを実行 ENTRYPOINT ["sh", "./gradlew", "bootRun"]5. Dockerコマンドでためす
・上記で作成したDockerFileのディレクトリで以下実行
・DockerFileのimageのビルド&コンテナ起動する (rmオプションで実行停止したときプロセス削除)# ビルドコマンド docker build -t my-java-app . # 実行 docker run -p 3000:8080 my-java-app --rm6. Docker-Compose作成
・上記で作成したDockerFileをコマンド1つで実行できるようにするためにDocker-Composeを作成
docker-compose.ymlversion: "3.7" services: javaapp: build: . ports: - "3000:8080"・
docker-compose up
を実行してみる・ローカルで動いていることを確認
7. 作成したDockerFileとDockerComposeをGithubにプッシュ
・サンプルとして以下に配置
https://github.com/harutotanabe09/SpringBootHelloWorldDocker.git
ワンポイント:Gitのサブモジュールでアプリ側にGitのDockerFileを入れると見分けがしやすい