Goalist Developers Blog

ChatworkからのEC2インスタンスの管理の自動化

どうも,エンジニアのナカノです.

今回は,Chatwork経由でのEC2インスタンスの管理の自動化の内容をご紹介致します.

過去に使ったことの無かった技術を,今回の開発で採用してみることにしました.

目 次
  • 背景
  • 作り方
  • 所感



背景

現在,クローリングデータの運用/納品チームは,EC2インスタンスの管理を次の様に行ってます.

  • 起動の場合:Chatworkのタスクを作成して、EC2の管理コンソールから起動を行う

  • 停止の場合:EC2の管理コンソールから停止を行い,Chatworkタスクを完了にする

これで運用すれば,Chatworkタスクの状態を見て,EC2インスタンスのstateを判断出来ます.

しかし,マニュアルで運用しており,抜け漏れがあり得ますし,何より面倒さがあります.

そこで,この一連のプロセスを自動化させて,同チームの業務改善を進めようと考えました.



作り方

自動化において,インフラはAPI GatewayLambdaといったサーバレス構成を採用しました.

この構成とChatwork Webhookの連携を利用して,イベント駆動な仕組みになる様にしました.

developer.chatwork.com

f:id:r-nakano:20200831160438j:plain


また,EC2インスタンスの自動管理の仕組みの,Gitプロジェクトの構成は次の様になります.

LambdaのハンドラーはGoで開発しました.これは,Goを使ってみたかったからです!

golang.org

ec2-serverless-manager
├── .circleci
│   └── config.yml
├── .gitignore
├── README.md
├── ci-package
│   ├── Dockerfile
│   └── bin
│       ├── deploy.sh
│       └── validate.sh
├── go.mod
├── main.go
├── pkg                  # ローカルパッケージ
│   ├── aws-ec2.go       # EC2インスタンスの検索,起動,停止を行う
│   ├── aws-ssm.go       # SSMパラメータの値を取得する
│   └── chatwork.go      # Chatworkへのメッセージ送信を行う
└── serverless.yml


Goのソースは,それぞれ次のようになります.ルールが少ないので実装が行い易いです.

各々のソースの実装は,次のリンク先のGitHubリポジトリの内容を参考にして行いました.

github.com

github.com

github.com

// main.go
package main

import (
    "encoding/json"
    "fmt"
    "strings"

    pkg "ec2-serverless-manager/pkg"

    "github.com/aws/aws-lambda-go/events"
    "github.com/aws/aws-lambda-go/lambda"
)

type CwWebhookRequest struct {
    WebhookSettingID string `json:"webhook_setting_id"`
    WebhookEventType string `json:"webhook_event_type"`
    WebhookEventTime int    `json:"webhook_event_time"`
    WebhookEvent     struct {
        FromAccountID int    `json:"from_account_id"`
        ToAccountID   int    `json:"to_account_id"`
        RoomID        int    `json:"room_id"`
        MessageID     string `json:"message_id"`
        Body          string `json:"body"`
        SendTime      int    `json:"send_time"`
        UpdateTime    int    `json:"update_time"`
    } `json:"webhook_event"`
}

func main() {
    lambda.Start(Handle)
}

func Handle(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
    // Lambdaで実行させたいことを実装する
}
// pkg/aws-ec2.go
package pkg

import (
    "os"

    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/ec2"
)

var region = os.Getenv("AWS_REGION")

var sess = session.Must(session.NewSession())
var svc = ec2.New(
    sess,
    aws.NewConfig().WithRegion(region),
)

func StartInstance(instanceId string) (*ec2.StartInstancesOutput, error) {
    input := &ec2.StartInstancesInput{
        InstanceIds: []*string{
            aws.String(instanceId),
        },
    }

    result, err := svc.StartInstances(input)
    return result, err
}

func StopInstance(instanceId string) (*ec2.StopInstancesOutput, error) {
    input := &ec2.StopInstancesInput{
        InstanceIds: []*string{
            aws.String(instanceId),
        },
    }

    result, err := svc.StopInstances(input)
    return result, err
}

func SearchInstance(instanceNm, state string) (*ec2.Instance, error) {
    input := &ec2.DescribeInstancesInput{
        Filters: []*ec2.Filter{
            {
                Name:   aws.String("tag:Name"),
                Values: []*string{aws.String(instanceNm)},
            },
            {
                Name:   aws.String("instance-state-name"),
                Values: []*string{aws.String(state)},
            },
        },
    }

    result, err := svc.DescribeInstances(input)

    if err != nil {
        return nil, err
    }

    var inst *ec2.Instance

    for _, reservation := range result.Reservations {
        for _, instance := range reservation.Instances {
            inst = instance
        }
    }

    return inst, err
}
// pkg/aws-ssm.go
package pkg

import (
    "os"

    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/ssm"
)

func GetSsmPrm(key string) string {
    svc := ssm.New(session.New(), &aws.Config{
        Region: aws.String(os.Getenv("AWS_REGION")),
    })

    response, _ := svc.GetParameter(&ssm.GetParameterInput{
        Name:           aws.String(key),
        WithDecryption: aws.Bool(true),
    })

    return *response.Parameter.Value
}
// pkg/chatwork.go
package pkg

import (
    "bytes"
    "net/http"
    "os"
)

type CwApiConfig struct {
    token   string
    roomId  string
    baseUrl string
}

var cwApiConfig = CwApiConfig{
    token:   GetSsmPrm("/xxxxxxxx/cw_api_token"),
    roomId:  os.Getenv("CW_ROOM_ID"),
    baseUrl: "https://api.chatwork.com/v2/rooms/",
}

func PostMsg(msg string) {
    param := "body=" + msg
    apiUrl := cwApiConfig.baseUrl + cwApiConfig.roomId + "/messages"

    request, _ := http.NewRequest("POST", apiUrl, bytes.NewBufferString(param))
    request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
    request.Header.Set("X-ChatWorkToken", cwApiConfig.token)

    response, _ := new(http.Client).Do(request)
    defer response.Body.Close()
}


以上を利用すると,Chatworkのルームでのタスクの作成/完了時に次が行われる様に出来ます.

  1. ChatworkのWebhookリクエストが,API Gatewayのエンドポイントに送られる

  2. API Gatewayは,Lambdaプロキシ統合を使って,Lambdaの呼び出しを実行する

  3. Lambdaは,リクエストの内容に基づいて,EC2インスタンスの有無を検索する

  4. もし該当のEC2インスタンスが存在すれば,それに対する起動/停止を実行する

  5. レスポンス用のメッセージをChatwork APIへ送り,特定のルームへ送信する



所感

Goには元々興味があったので,今回の自動化の対応でチャレンジすることが出来て良かったです!

一方で,初めて知る部分が色々とあったのもあり,次の点を何とかするのに地味に苦戦しました.

  • Go Modulesを利用したGoプロジェクトの構築

  • Webhook連携でのワークフローの無限ループの回避

最終的には何とかすることが出来て,これらの困難を乗り越えたことが良い経験になりました.

引き続き自動化の対応を進めていき,業務やシステムをより良い方向へ改善出来ればと思います.

次回は,このシステムのCI/CDの部分についてお話しようと思います.ご期待下さいませ~.

社内向けETLシステムのバッチ運用の自動化

どうも,エンジニアのナカノです.

今回は,社内システムのバッチ運用の自動化の内容をご紹介致します.

社内では,クローリングデータを加工するために,ETLシステムが存在します.

このシステムのEC2インスタンスのAMI運用を,今回は自動化しました.

目 次
  • 背景
  • 作り方
  • 所感



背景

今までのETLシステムはLAMPの様なステートフルなもので,サーバ自体の運用が必須でした.

また,同様なシステムが運用の都合で複数出てきたため,コスト面で問題になってきました.

そのため,コストダウンのために,API,バッチ,DBを全て切り分ける様に構成を見直しました.

以下の画像は,ETLシステムのサービスとCI/CDのインフラ構成図のサンプルです.

f:id:r-nakano:20200817164950j:plain f:id:r-nakano:20200817164954j:plain f:id:r-nakano:20200817164957j:plain

大半をステートレスな構成に変更することが出来たのですが,バッチサーバはそれが困難でした.

そのため,バッチサーバのAMIは既存のものをベースとして,構成管理の自動化を進めました.



作り方

色々と調べた結果,主に次の様な構成にしました.

  • GitHubと連携して,CircleCIをパイプラインとして使う

  • CodeBuildでPackerとAnsibleを実行し,AMIを作成する

CircleCIを選んだのは,パイプラインの設定が他のCI/CDサービスよりも細やかだからです.

他には,社内のCI/CDツールでこのサービスが使われているからというのもあります.

また,CodeBuildを利用したのは,CircleCIの無料プランの制限問題を回避するためです.

ビルドに時間がかかるため,CircleCIはあくまでGitHubとCodeBuildの間の仲介者と使っています.

circleci.com

docs.aws.amazon.com

www.packer.io

docs.ansible.com

dev.classmethod.jp


CircleCIからCodeBuildの連携は,CodeBuildに関するAWS CLIを使って行っています.

また,CodeBuildでのコンテナ上では,Packerのコマンドを実行する様にしています.

f:id:r-nakano:20200831151218j:plain

ところで,バッチサーバには管理や利用の有無が不明やプログラムが多く存在します.

これらは,AMIの新規作成や更新の際にS3から必要な分のみをプルする様にしました.

この辺りは弊社の技術負債の1つであり,どこかで何とかしたいところですね....



所感

開発と運用のそれぞれが楽になる案を探し,一旦の落としどころを見つけたという感じですね.

ステートレスな構成に出来ていないのが無念ですが,フローを何とか固められて良かったです.

あとは,Codeシリーズはとても便利ですが,慣れていないとハマり易い印象がありますね.

CodeBuildは,忘れた頃にはIAM関連の設定やネットワーク制約等でハマっってしまいますね....

引き続き,チームで自動化を進めていき,社内外の困りごとを技術で解決していきます.

EC2インスタンスのバックアップの自動化

どうも,エンジニアのナカノです.

今回は,EC2インスタンスのバックアップの自動化の内容をご紹介致します.

バックアップと言っても,今回は特にAMIの定期的な自動作成についてです.

目 次
  • 背景
  • 作り方
  • 所感



背景

社内では,開発/運用のライフサイクルの改善で,ステートレスなシステム構成を目指しています.

一方,古いシステムでステートを持つものが存在し,実際に現役で稼働しているものもあります.

特にこの様なシステムのバックアップの仕組みが整っておらず,これが技術負債となっていました.

今回は技術負債の解消も込めて,自動的なバックアップの設計/開発を進めることになりました.



作り方

構成

EC2インスタンスのバックアップの方法としては,AMIスナップショットの二種類があります.

スナップショットだと料金が発生するため,AMIの自動管理の仕組みを作ることになりました.

調べてみるとAWS Backupが利用出来そうで,今回はこれを使って仕組みを作ることにしました.

去年まではLambdaやCloudWatch Events等で構築する必要があったので,これは便利ですね!

docs.aws.amazon.com

f:id:r-nakano:20200817145335j:plain

セットアップ

以下では,主にAWS Backupの各種リソースの作り方をご紹介致します.


プランとルールの作成

AWSマネジメントコンソールにログインし,次にAWS Backupの管理画面を開きます.

管理画面内のマイアカウント > バックアッププランを開き,バックアッププランを作成のボタンを押します.

今回は新しいプランを立てるを選び,プランやルールの名前は画像の様な感じで設定しました.

f:id:r-nakano:20200817151029j:plain


ジョブのスケジュールは頻度を毎日とし,バックアップウィンドウはカスタム設定で行いました.

開始時間は午後5時(UTC)で,1時間以内に開始し,1日以内に完了する様に設定しました.

日本時間で言えば,毎日深夜2時から1時間以内にAMIが自動作成され,この作成が1日以内に終わるというルールです.

また,有効期限を2日としました.つまり,AMIが1日に1個作られて,2日でローテートされるということです.

f:id:r-nakano:20200817151035j:plain


その次にタグ設定を行い,プランを作成のボタンを押してバックアッププランを作成しました.

基本的には,これらの設定で事足りるかと思います.その他の設定は場合に応じて行う感じです.

f:id:r-nakano:20200817151043j:plain


リソースの割り当て

その後は,マイアカウント > バックアッププランで作成したプランの詳細画面を開きます.

詳細画面内のリソースを割り当てるのボタンを押し,プランとリソースの紐づけの設定を行います.

IAMロールはデフォルトを選びました.また,リソースを割り当てるの設定は次の様に行いました.

割り当てを複数行いたい場合は,割り当てを追加のボタンを押して同様な設定を行えばよいです.

  • 割り当て単位:リソースIDを選択

  • リソースタイプ:EC2を選択

  • インスタンスID:紐付けたいEC2インスタンスのIDを選択

f:id:r-nakano:20200817154056j:plain



所感

Amazon DLMもそうですが,1つのサービスでシステムを簡単に管理出来るのは素晴らしいですね!

AWSでは開発/運用をサポートするものがここ数年で続々と登場し,目を見張るものがあります.

こういったものがあると,工数をあまりかけずにライフサイクルの改善を進められるので良きです.

今後も技術のアップデートを見逃さない様にして,システム改善の最適化を都度に求めたいです.

近況報告と今後の発信について

f:id:r-nakano:20200817175530j:plain

お久し振りです.エンジニアのナカノです.

前回の記事の執筆から,2年と1カ月振りですかね.発信が滞ってしまっておりました.

執筆するのがかなり久々で,ちょっと緊張しています.笑

間が空き過ぎているので,まずは私の近況報告でもさせてください.

目 次
  • 近況報告
  • 今後の発信



近況報告

初配属後から2年間は,運用系のチームと開発系のチームを行き来していました.

現在は,技術戦略のチームで,システムの開発/運用/改善を行っております.

具体的には,大きな対応ですと,ここ数年では主に次の業務を対応させて頂きました.

受託開発案件の対応

  • 不動産関連の情報まとめサイトのインフラ開発

  • 外国人雇用の就労ビザの管理サービスのインフラ設計/開発

社内システムの新規,リニューアル対応

  • 問い合わせ基盤のインフラ/バックエンドの設計/開発

  • 人材業界向けのメディアサービスのインフラ設計/開発

  • 求人媒体用のクローラーシステムのインフラ設計/開発

  • ETLシステムのインフラ/バックエンドの設計/開発

  • 各種サービスの管理システムのインフラ設計/開発

他には,AWS周りや各種インフラの運用/改善等は,社内を横断してサポートしております.

ここ数年は引き続きエンジニアとして,以上の様な感じで活動しておりました.

以前の執筆時と比べて,実に色々な経験をさせて頂き,成長することが出来ました.



今後の発信

先月よりチームの指針の一つとして,自動化100というものが設けられました.

これは,マニュアル業務やシステムを自動化し,困り事や課題を解決しようというものです.

自動化の内容は,技術戦略のチームが一丸となって発信して参ります.

技術ブログに関しまして,ご興味がありましたらお読み頂けますと幸いです.

GASによるイベント連絡の自動化

はじめまして、ゴーリストのキムと申します!

この記事では、Google Calendarのイベントの連絡の、ChatWorkへの自動投稿の仕組みについてお話します。

この仕組みを作るために、GAS(Google Apps Script)という技術を使いました。

これから、仕組みの詳細を説明させていただきます!

背景

今までは、チーム内でのミーティングの度に、誰かがChatWorkで知らせる必要がありました。 ミーティングによっては、ChatWork経由での連絡を知って準備を行うことがあります。

このような連絡は必要ですが、マニュアルでの連絡を毎回対応するのは負担がかかります。 そこで連絡を自動化しましょうという話になり、自動投稿の仕組みを作ることになりました。

作り方

メッセージの自動投稿システムは、GAS(Google Apps Script)を利用して開発しました。

f:id:KimChanHyung:20200811105001j:plain
イメージ:https://www.asobou.co.jp/blog/bussiness/gas

実際には、以下のコードのように、Google Calendarの一日のイベントから探し出し、条件にマッチするイベントがあれば処理を行います。

探した後にはChatworkのAPIを利用して自分が指定したメッセージを指定したChatworkルームに送ることが出来ます。

for (let i = 0; i < events.length; i++) { 
    const title = events[i].getTitle();
    if( title === "TS Weekly Meeting"){
      mtgFlag = true;
    }
  }

また、システムの実行も自動で行うようにするために、メッセージ投稿の実行のスケジューリングを設定しました。

f:id:KimChanHyung:20200811110730p:plain
GASのトリガー設定

所感

今回の対応で、Google Calendarのイベントの定期連絡を自動で行えるようになりました。

また、この仕組みは色々なパターンへ汎用化させることが出来そうで、大変便利です。

しかし、GASでは1時間毎での設定しか出来ず、実行のタイミングはランダムで、細かい制御が出来ません。

例えば、午前9時から午前10時で設定した場合、この1時間のどこかで実行のタイミングがランダムに決まります。

f:id:KimChanHyung:20200811112552p:plain
GASトリガーの時間設定

まとめ

以上、GASによるGoogle Calendarのイベント連絡の自動化のお話でした。

これからも様々なブログを投稿しますので、お読みいただけますとうれしいです!

Which Python Package Manager Should You Use?

f:id:vivek081166:20190612133948p:plain
source : https://realpython.com/

Nowadays Python is everywhere  - academics, data science, machine learning, enterprise application, web application, scripting... you name it python is everywhere. Whatever you do, python is there either to help you or give you a headache.

Let's say, you have learned python programming and ready to use to develop applications, surely, as that sounds great, you jump into coding python scripts and eventually start installing python packages. From there one follows a dangerous path into a developer’s nightmare.

f:id:vivek081166:20190612152119p:plain
source : https://xkcd.com/1987/

Package installation may lead to having incompatibility issues or make other applications unworkable. And you may discover that your code does not work on some machines while it just works flawlessly on your local machine. Why??? It's because of the Python environment.

To save yourself from incompatibility issues, a separate virtual python environment needs to be created for a project.

A virtual environment is a bunch of scripts and directories that can run python isolated. By using a virtual environment, each python project can have its own dependencies regardless of other projects and system python environments.

In this blog post, I would like to share with you my environment for working with data and doing machine learning. You most definitely do not need to copy anyone's setup but perhaps use the one that best fit for you.

f:id:vivek081166:20190612134946p:plain

Every programmer has different preferences when it comes to their programming environment vim versus emacs, tabs versus spaces, virtualenv versus anaconda.

To start with, we need to talk about pip. A python person {what :O} knows that pip is Python's package manager. It has come built into Python for quite a while now, so if you have Python, you likely have pip already.

pip installs packages like tensorflow and numpy, pandas and jupyter, and many more along with their dependencies. Many Python resources are delivered in some form of pip packages. Sometimes you may see a file called requirements.txt in someone's folder of Python scripts. Typically, that file outlines all of the pip packages that the project uses, so you can easily install everything needed by using

pip install -r requirements.txt

As part of this ecosystem, there's a whole world of version numbers and dependencies. You sometimes need to use different versions of a given library for different projects that you are working on.

So you need a way to organize groups of packages into different isolated environments. Otherwise, looking at the version errors you would want to bang your head against the wall.

There are two popular options currently for taking care of managing your different pip packages virtualenv and anaconda.

f:id:vivek081166:20190612145609p:plain

1) Virtualenv

Virtualenv is a package that allows you to create named virtual environments where you can install pip packages in an isolated manner. This tool is great if you want to have detailed control over which packages you install for each environment you create.

For example, you could create an environment for web development with one set of libraries, and a different environment for data science. This way, you won't need to have unrelated libraries interacting with each other, and it allows you to create environments dedicated to specific purposes.

# install
pip install virtualenv

# create environment
virtualenv venv 

# activate environment
source venv/bin/activate

f:id:vivek081166:20190612141916p:plain

2) Anaconda

Now, if you're primarily doing data science work, Anaconda is also a great option. Anaconda is created by Continuum Analytics, and it is a Python distribution that comes preinstalled with lots of useful Python libraries for data science. Anaconda is popular because it brings many of the tools used in data science and machine learning with just one install, so it's great for having a short and simple setup.

Like Virtualenv, Anaconda also uses the concept of creating environments so as to isolate different libraries and versions. Anaconda also introduces its own package manager called conda from where you can install libraries.

Additionally, Anaconda still has a useful interaction with pip that allows you to install any additional libraries which are not available in the Anaconda package manager.

Follow the instructions to download and install anaconda from here

# create environment
conda create --name test-env

# activate environment
conda activate test-env

# install additional packages
conda install tensorflow

To add more you have a nice UI to manage your projects and environment
f:id:vivek081166:20190614111628p:plain

So... which one to use, virtualenv or anaconda?

Well, it's nice to try out different libraries on both virtualenv and anaconda, but sometimes those two package managers don't necessarily play nicely with each other on one system.

In my case, I have opted to use both, but I manage the whole thing using a library called pyenv.

Conceptually, pyenv sits on top of both virtualenv and anaconda and it can be used to control not only which virtualenv environment or Anaconda environment is in use, but it also easily controls whether I'm running Python 2 or Python 3.

pyenv local 2.7.10
pyenv activate py27_tf12


pyenv local 3.5.2
pyenv activate py35_tf12

One final aspect of pyenv that it has an ability to set a default environment for a given directory. This causes that desired environment to be automatically activated when you enter a directory.

~/code $ cd myproject
(py35_tf12) ~/code/myproject $

I find this to be way easier than trying to remember which environment I want to use every time I work on a project.

So which package manager do you use?

It really comes down to your workflow and preferences. If you typically just use the core data science tools and are not concerned with having some extra libraries installed that you don't use, Anaconda can be a great choice since it leads to a simpler workflow for your needs and preferences.

But if you are someone who loves to customize your environment and make it exactly like how you want it, then perhaps something like virtualenv or even pyenv maybe more to your liking.

There's no one right way to manage Python libraries, and there's certainly more out there than the options that I just presented.

As different tools come and go, it's important to remember that everyone has different needs and preferences, so choose for yourself the best one that fits your needs.

That's it for this post, my name is Vivek Amilkanthwar. See you soon with one of such next time; until then, Happy Learning :)

Kerasくんとgeneratorの魔法

f:id:c-pattamada:20190530112343j:plain
魔法の書がありました

ゴーリストのチナパです!さてさて、今回は面白いのがありますよ〜

タイトルがちょっとハリーポッターっぽくて失礼します、機械学習の記事です。

機械学習というと、ビッグデータが思いつくと思います。 大量のデータで数日感学習させたり…

でも一つだけ問題があります

51ギガ?!

可愛そうなパソコンが諦めました。そんなRAM持ってませんって。

大量のデータで学習した時にこういうのもよくあります。私の場合には、数ギガバイトのcsvファイルの文字データをベクトル化しようとして、このようなことになりましたが、画像処理・音声分析の世界にはもっと頻繁でしょう。

ここではPythonの便利な機能「generator」を使うと良いです。

「generator」?なにそれ

range(10)

これもgeneratorです。何度も見たかと思います。

つまりgeneratorはループに使えるiterator系のobjectです

for x in range(10):  
    print(x)  #0~9がprintされます

上記のようにfor ループに使えますが、generator の本当の取り柄は全てのデータを同時にメモリー(RAM)にロードしていないことです。

ただし、このようにしますと:

my_gen = range(10)
for x in my_gen:
  print(x) #無事0~9がprintされます

# 二回めはうまく行かない
for x in my_gen:
  print(x)  #何もprintされない

これはメモリーに保存されてないからです。 ただし、データ量が多すぎてパソコンが泣いている私たちにはこの機能こそが素晴らしいです。

自分のgeneratorはどうやってつける?

Pythonにはメソッドの中にreturnを使う場合がよくありますが、yieldを使う場合もあります。メソッドにはyieldが使われてるとそのメソッドがgeneratorになります。

以下のメソッドが簡単なgeneratorです。nx0 からnx(n-1)までの数字を出します。

def my_generator(n):
  i = 0
  while i < n:
    i += 1
    yield n*(i-1)

for x in my_generator(5):
  print(x) # 0, 5, 10, 15, 20のようなものが順番にprintされます

でもこんなのはどうやって機械学習に活かせますか?

そうですね、本題に着きました。

keras のfit_generator()メソッドを利用します。このために、永遠までデータを出してくれるgeneratorメソッドが必要です。

つまり以下のようなものは◎です。

def gen():
  while True:
     yield 1 # ただしこんなデータ要りません!

すみません、しっかりします。前提として、データをcsvファイルであると想定しています。これはもちろん必須ではありませんが、pandasを便利に使えるし、文字データならcsvにまとめやすいので、そういうことにしましょう。

gist.github.com

ポイントとしては while Trueの中に、 pd.read_csv(skiprows=i, nrows=batch_size) があることです。 これはcsvデータの必要な部分(ここでは32行)をデータ化しようとします。 この例には、nullデータを外すための処理も入れてます、これは事前に掃除されたデータであれば無くしてもいい部分ですね。

yield data['input_x'], data['outputs_y']

もありますが、複数のインプットが必要な場合には

yield [data['input_x1'], data['input_x']], data['outputs_y']

見たいにまとめたらうまく行きます。

学習させましょう!

gist.github.com

kerasのfit_generatorメソッドで学習データとバリデーションデータのそれぞれのgeneratorを作っておきます。

ここの変わったところが

steps_per_epoch= train_size // batch_size

あたりですね。全てのデータがメモリーに入っていない上、generate_input_data() のメソッドが永遠まで続くようになってますので、1epochの大きさが分かるために、設定しないといけません。

お時間たっぷりかけると思いますが、無事大量のデータで学習できるようになってます!

まとめ

今回は

  • Pythonのgeneratorについて学びました
  • kerasで使えるgeneratorを作成しました
  • model.fit_generator() を利用しました。

ここまで読んでくれてありがとうございます。 では、また!