Goalist Developers Blog

ngx-datatableでソートしつつ特定の行を固定する!

angularでデータグリッド表示するのにngx-datatable使ってます

github.com

フロント側でのソート機能がついていますが、こんな感じで合計行まで動いてしまうのですよね

f:id:y-iio:20180413180915g:plain

突っ込んだデータの合計行だけは一番下に固定したいという望みを叶えるべく
ゴリラ的な方法でズズイと無理やりやってみました

マルチソートの対応はしない。漢らしい!

<ngx-datatable
        #dataTable
        [rows]="rows"
        [columns]="columns"
        [sorts]="sorts"
        (sort)="onSorted($event)">
</ngx-datatable>
public rows = [];
public columns = [];
public sorts = [];

@ViewChild('dataTable') private dataTable: DatatableComponent;
private ascSortedColumn: string = '';

public onSorted(event): void {
    // ここにくるとき、this.dataTable._internalRowsは常に昇順ソートがかかった状態になっている
    const columnName: string = event['column']['name'];
    // 一度明示的に昇順ソートした後だったら、ここで無理やり降順ソートの設定に書き換える
    if (this.ascSortedColumn === columnName) {
        this.ascSortedColumn = '';
        event['sorts'][0]['dir'] = 'desc';
        this.sorts = [{
            prop: event['sorts'][0]['prop'],
            dir: 'desc'
        }];
        this.rows = [...this.rows]; // 降順ソートを適用
        setTimeout(() => {
            this.moveSumRow(); // ライブラリ側の降順ソート処理が終わった頃合いを見計らう
        }, 100);
    } else {
        this.ascSortedColumn = columnName;
        this.moveSumRow();
    }
}

// ライブラリ側のソート処理が終わってから、合計行をいちばん後ろに移動させる
private moveSumRow(): void {
    const tmpRows = this.dataTable._internalRows.concat();
    const sumRowIndex: number = tmpRows.findIndex((row) => row.hasOwnProperty('x1field') && row['x1field'] === '合計');
    if (sumRowIndex < 0) {
        return;
    }
    const sumRow = tmpRows[sumRowIndex];
    tmpRows.splice(sumRowIndex, 1); // 合計行をいちばん後ろに移動
    tmpRows.push(sumRow);
    this.sorts = []; // テーブルのソートを解除 // ここで解除しておかないと合計行含めてソートし直されてしまう
    this.dataTable.sorts = []; // ほんとうにむりやりテーブルのソートを解除
    this.rows = [...tmpRows]; // 表を再描画
}

こんなかんじで、一瞬ペイッ!ガタッ!と動きます

f:id:y-iio:20180413180948g:plain

すごい力技だ!
現在選ばれているソート条件アイコンを見えなくすることで全てをうやむやにする!

力という名のパワーで全てを解決しました
男にはやらなきゃならねえ""瞬間とき""がある

Javaの未来

こんにちは、ゴーリストのチナパです。去年の9月より、オラクルさんがJavaをよりはやく更新するといい、同じ9月でJava 9がリリースされ、つい最近Java 10もリリースされました。しかも、今までみんなが使ってたJava 8は2019年の1月までしかアップデートされないらしいです。

f:id:c-pattamada:20180406164916j:plain

最近のオラクルのJava Client Roadmap Updateと言う物でもっと詳細が書かれましたのでそれを軽くサマリーしようと思いました。

http://www.oracle.com/technetwork/java/javase/javaclientroadmapupdate2018mar-4414431.pdf (英語です)

スケジュール

一番重要な情報はどんな風に更新が行う予定なのか、とどんな風にサポートが続くのか。故にそこから始めたいと思います。

Java 8は2019年1月まで公式アップデートが行う予定ですが、個人用(つまり、コーポレート用ではない)のためになら2020年までサポートが続くらしいです。

Java 11 (Java 18.9) は2018年の9月でリリースされる予定です、そしてそれは長期的なサポートに入るそうです(9と10は入りません)。

Java SE 11 (18.9) Platform JSR (384)

Java FX がJava 8 で2022年までサポートが残る予定ですが、Java 11からは外されている。swingとawtがJava 11に残るので、せめて2026年まで使えるらしいです。

変更点

では、Java 10の面白い更新に入りましょう。大きく分けると書き方の変化と裏の改善があります。追加機能いっぱいありますが、一番面白いと思った3つを以下にまとめてます。

変数の種類をコンテクストで理解する

var list = new ArrayList<String>();  // ArrayList<String>と理解してくれます

これはちょっとワクワクですね、自分はパイソンもよく使ってるのでちょっとだけでもコードが綺麗になりそう。一方、下手すると分かりにくくなりますね。 すでに存在してるコードの中のvar 変数は影響されないらしいです(つまり[code]int var = 5;[/code] がエラーを出さないです) そして、イニシャライズされない所にvarが使えない。

var x; //うまく行きません
var x, y = 0; //おっけー

裏の改善

スレッドローカルハンドシェーク:

マルティスレッドのセーフポイントの改善の機能です。結果的に現在のグローバルセーフポイント(全スレッドが中止する時)でしかできない活動をこのハンドシェーク機能で行えることによって効率性が高くなるようです。

CDSの改善=> AppCDS

CDSはJDK 5からありまして、ロード時間を減らすために編集しないクラスをarchiveし、そのarchiveされたクラスを高速でロードできるようになるシステムです。今まで、BootstrapClassLoaderしかできなかった事でしたが、この際AppClassLoader(故にAppCDS)もできるようになるためにエンタプライズ系のアプリのロード時間が結構減らせるらしいです。

他もありますので、下にオラクルの記事をリンクします!

オラクル、Java SE 10の一般提供を開始 | Oracle 日本

IaC by Terraform ~DAY2: Terraform Commands (1)~

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

3月中旬辺りから段々と暖かくなってきましたね.

よく通る川沿いの道では沢山の桜の木が花を咲かせており,通勤時が非常に楽しいです.

さて,今回もTerraformに関する記事です.

前回は実行環境の準備に関する内容の記事でした.

今回の内容は,よく使われるTerraformのコマンドに関してです.

目 次
  • よく使われるコマンド
    • init
    • fmt
    • validate
    • plan
    • apply
    • destroy
  • 最後に

よく使われるコマンド

Terraformを用いてインフラリソースを作るには,まず.tfという拡張子の設定ファイルを作成します.

その後にリソース作成用のコマンドを実行すると,各.tfファイルの情報がある一つのJSONファイルにまとめられます.

これをterraform.tfstateというのですが,Terraformはこのファイルを基準にしてリソースの作成・改変・削除を行います.

以下は,それらを行う際によく用いられるコマンドです.

init

リソースの作成・改変・削除を行う際にまず行うべきコマンドです.

これが実行されると,実行場所に.terraformというディレクトリが作成されます.

このディレクトリがないとリソースの作成・改変・削除が行えないため,何よりも一番重要なコマンドです. www.terraform.io

fmt

設定ファイルのフォーマットを行う際に使われるコマンドです.

ただ,使用するエディタによってはフォーマット機能の付いたパッケージがあるため,人によってはあまり使われないかもしれません. www.terraform.io

validate

設定ファイルに文法エラーがあるか否かをチェックする際に使うコマンドです.

便利ですが,次に紹介するplanというコマンドが文法エラーを含めたエラーの検知を行ってくれるため,これもあまり使われないものかもしれません. www.terraform.io

plan

どういったリソースを作成,改変或いは削除するのかをTerraformが決めるために使われるコマンドです.

この実行によってterraform.tfstateと設定ファイルたちの内容の差分を検知し,Terraformの振る舞い方が決まります.

そのため,initコマンドの次に必須なコマンドであると言っても過言ではないでしょう.

ところで,planコマンドには次のよく使われるオプションがあります.

-target=resource

これを用いることで,ある特定のリソースのみに対してplanコマンドを実行させることが出来ます.

ある複数個のリソースに対してplanを行いたいのであれば,このオプションをplanに複数個並べて付ければよいです.

-destroy

削除対象のリソースたちの情報を見るためにこのオプションが使われます.

Terraformのリソース情報の差分認識を観察するには割と重要なオプションです.

-var 'foo=bar'

変数設定されているがその値が空の場合,このオプションが必要です.

このオプションを付けずにコマンドを実行すると,空の変数の値を対話的に要求されます.

その場合は,画面に変数値を入力してコマンド実行の続きを行えば大丈夫です.

-var-file=foo

Terraformには.tfvarsという拡張子のファイルがあり,これは変数設定を行う際に使われるファイルの一つです.

ファイルの内容は一見すると環境変数の設定ファイルの様に見えるかもしれません.

このオプションを使う場合は,オプション値に該当の.tfvarsファイルのパスを指定します.

もしこのオプションを使わない場合は,画面上で.tfvarsに書かれている変数の値を対話的に一つずつ要求されます.

www.terraform.io

apply

planコマンドの結果を元にリソースを作成・改変・削除するために使われるコマンドです.

この実行時でもエラーが検出されることがあるので,planが正常に終了したからといって油断するのは禁物です.

なお,このコマンドでは次のオプションがよく使われます.

-auto-approve

Terraformのバージョンが0.11.0になってからこのオプションが登場しました.

それ以前のバージョンではapplyを実行すると実行が終了するまでコマンドの処理が動き続けていました.

ところが,それではオペレーションミスなどが偶発することもあり,0.11.0以降では実行の許可を対話的に求められる様になりました.

さて,このオプションですが,その「実行許可の対話的要請」をスキップする様にしてくれるものです.

これを付けてapplyを実行すれば,0.11.0以前の様なapplyの挙動になります.場合によっては便利だったりします.

-target=resource, -var 'foo=bar', -var-file=foo

planのオプションにあるものと同様です. www.terraform.io

destroy

作成済みのTerraformで管理されたリソースを削除する際に使われるコマンドです.

実はapplyの実行時でもリソースが削除されることもあるのですが,違いは「destoryは削除のみに使われて,applyでは『リソースを作り直す」挙動を起こす時にリソースが削除される」といった感じです.

このコマンドでも次のよく使用されるコマンドがあります.

-auto-approve

applyのオプションにあるものと同様です.もしこれを使うのであれば,destoryの実行の前にterraform plan -destroyをすべきです.

最後に

よく使われるコマンドは上記の通りですが,基本的には

  • terraform init
  • terraform plan
  • terraform apply
  • terraform destroy

の4つを覚え,使い慣れる様にしておくとよいでしょう.

それでは,今回はここまでと致します.

次回は「場合によって役立つコマンド」についてご紹介致します.

EC2でChromeヘッドレスを動かす

AWSのEC2でChromeをヘッドレスモードで動かしてクローリングしたい!
そこに至るまでにはいくつかの壁があります。

  • Amazon Linuxでは上手くいかない
  • Chromeだけでなく、日本語フォントが必要
  • ChromeとChromeDriverの対応バージョンを合わせる必要がある

この辺を乗り越えたときのメモを残しておこう思います。最後におまけとして「ページのロードが終わらないでタイムアウトする」というSelenium WebDriverあるあるを解決する方法も載せておきます。

環境

  • EC2(OS:Ubuntu)
  • Selenium WebDriver for Java 2.53.0

手順

とりあえずUbuntuでEC2インスタンスを立てる

今回はインスタンス作成ボタンを押したときに出てくる一覧から以下を選択。
Ubuntu Server 16.04 LTS (HVM), SSD Volume Type

Chromeをインストール

/home/ubuntu/chrome-setup を作成し、以降の作業はそこで行います。

mkdir /home/ubuntu/chrome-setup
cd /home/ubuntu/chrome-setup

Chromeはdebパッケージをダウンロードしてインストールします。
ただし、以下のように最新版をインストールするとChromeDriverが対応するバージョンを超える場合があります。

wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb

ChromeとChromeDriverのバージョンの対応はChromeDriverの ダウンロードページで確認できます。 今回は61が欲しかったのでslimjetのサイトから落としました。
ブラウザから落とす場合は以下のURLで落とせます。
https://www.slimjet.com/chrome/google-chrome-old-version.php
クローラ云々は別として、Google公式ではChromeの最新バージョンしかダウンロードできないので有用なサイトです。
wgetでdebパッケージを落とす場合は以下です。

wget https://www.slimjet.com/chrome/download-chrome.php?file=lnx%2Fchrome64_61.0.3163.79.deb

ダウンロードしたので、インストール 。

sudo dpkg -i download-chrome.php?file=lnx%2Fchrome64_61.0.3163.79.deb

なんかめっちゃエラーでて怒られるので、 依存モジュールをaptでインストール。

sudo apt update
sudo apt -f install -y

インストール確認。

which google-chrome

こんな感じで表示されれば多分OK→ /usr/bin/google-chrome

日本語フォントをインストール

このままだと日本語がお豆腐になってしまうので、今回はIPAフォントをインストールします。
まずはunzipをインストール。

sudo apt install unzip

IPAフォントをダウンロードしてunzipしてfontに置く。

wget --content-disposition IPAfont00303.zip http://ipafont.ipa.go.jp/old/ipafont/IPAfont00303.php

sudo unzip IPAfont00303.zip -d /usr/share/fonts/

フォントキャッシュクリア

sudo fc-cache -fv

おまけ

以上でEC2上でChromeをヘッドレスモードで動かす準備はできたわけですが、Javaのコード上で実際にヘッドレスを指定する方法を載せておきます。
ついでにページロードが終わらなくてタイムアウトする問題にはpageLoadStrategyというパラメータが有効です。Chromeでは指定しない場合はnormalが指定されていますが、noneを指定すればタイムアウトは回避できます。
ただし、noneの場合はきちんと対象の要素を待つようなロジックにしないと思った通りの動作にならない場合があります。
また、pageLoadStrategyに指定できるのはnormal eager noneの3種類ですが、eagerはChromeでは認識されませんでした。

private static WebDriver getChromeDriver() {     
    System.setProperty("webdriver.chrome.driver", "path to your chromedriver");
    
    ChromeOptions chromeOptions = new ChromeOptions();
    chromeOptions.addArguments("--headless", "window-size=1280,1024"); // xvfbとか一切無しでdislayサイズも指定できちゃう
    
    DesiredCapabilities capabilities = DesiredCapabilities.chrome();
    capabilities.setCapability(ChromeOptions.CAPABILITY, chromeOptions);
    capabilities.setCapability("pageLoadStrategy", "none"); // normal eager none
    return new ChromeDriver(capabilities);
}

Jenkinsのスレーブを使い捨てる

AWS環境でJenkinsを利用してビルドとかしているのですけど
ビルドサーバ1台じゃさばききれねえ〜
重めの処理するためにインスタンスタイプあげたい〜
でも常に使いたいわけじゃなし〜ビルドサーバ増やしても管理めんどいし〜
みたいな悩みありませんか、私はあります

そんな悩みをJenkinsのスレーブを使い捨てることで解決します

かんたんにいうと

  • マスターJenkins君が
  • EC2インスタンスを自動で立てて
  • ssh経由でジョブ実行させて
  • 使い終わったらインスタンスターミネートしてくれる

環境

EC2
Amazon Linux AMI 2017.09.1.20180307 x86_64 HVM GP2

Jenkins
ver. 2.111

こんな構造にしました

f:id:y-iio:20180320153722p:plain

ネットワーク設定についてはこちら

developers.goalist.co.jp

手順

  1. マスターJenkinsの初期設定
  2. スレーブになるインスタンスのAMIを用意
  3. マスターJenkinsからスレーブ作成する設定
  4. マスターJenkinsからスレーブでビルドするテスト

詳しく

1. マスターJenkinsの初期設定

1.1. このあたりを参考にJenkinsのインストール

Installing Jenkins on Red Hat distributions - Jenkins - Jenkins Wiki

qiita.com

1.2. webサーバーたてて8080ポートからまわしてあげる

qiita.com

これやったら Jenkins > Jenkinsの管理 > システム設定 > Jenkinsの位置 > Jenkins URL
からポート番号を抜く
「リバースプロキシの設定がおかしいようです。」と出てしまうので、、

1.3. gitの設定
ビルド用のソースはgitから落としてくるつもりなので、、

なにはなくともgitインストール

qiita.com

httpsでユーザー名とパスワード使う方式でcredential登録

認証情報 > グローバルドメイン > 認証情報の追加

  • 種類:ユーザー名とパスワード
  • スコープ:グローバル
  • ユーザー名:githubアカウントのメールアドレス
  • パスワード:githubアカウントのパスワード
  • ID:わかりやすい名前をつけます(例 github)
  • description:わかりやすい説明をつけます(例 xxxx's github account)

2. スレーブになるインスタンスのAMIを用意

2.1. スレーブ用のセキュリティグループを作成
マスターのセキュリティグループに対してssh許可します
あと自分のIPにもssh許可

f:id:y-iio:20180320154035p:plain

2.2. インスタンスを新規作成
t2.microとかでいったんok

Jenkinsジョブが動くようにJava8の実行環境は用意

road288.hatenablog.com

スレーブでの実行ユーザーになるec2-userに/var/jenkins以下のパーミッションを与える

sudo mkdir /var/jenkins
sudo chown ec2-user:ec2-user -hR /var/jenkins

時計もしかと合わせます

qiita.com

こちらにもgitインストール
スレーブ側には認証情報を持たせる必要ないです

他、npmとかビルド内容の必要に応じて入れときましょう

2.3. インスタンスを停止し、AMI作成
型をとってやる
この型を使ってマスターはインスタンス作成します

Amazon EBS-Backed Linux AMI の作成 - Amazon Elastic Compute Cloud

型って何、、

developers.goalist.co.jp

AMIが定まったらこのインスタンス自体は削除してしまってok

3. マスターJenkinsからスレーブ作成する設定

こちらの説明が大変詳しくわかりやすいです

qiita.com

最終的にはこんなかんじの設定で使ってます

f:id:y-iio:20180320154324p:plain

f:id:y-iio:20180320154338p:plain

4. マスターJenkinsからスレーブでビルドするテスト

テストじゃ〜〜ドンドンパフパフ

てきとうなジョブを新規作成!

general > 実行するノードを制限
でさっき設定に書いたラベルを入力!

ビルド > シェルの実行
でてきとうなシェルを書く!

echo "$(date) : $(hostname)" >> /tmp/hostname

実行!

インスタンスたちあがった〜

f:id:y-iio:20180320154432p:plain

ノードに追加された〜

f:id:y-iio:20180320154444p:plain:w300

ジョブが通った〜

f:id:y-iio:20180320154510p:plain

ウオオアア〜〜〜

これでやりたい放題だ!!!!!やったぜ!!

 

AWSのネットワーク設定をばおさらい

EC2インスタンスはときどきたてるけどネットワーク設定ってあんまり知らなくないですか?私はよく知りません
そんなこんなでおさらいダァーー(嵐吹くこの街がお前を抱く)

手順

  1. VPCを作る
  2. サブネットを作る
  3. ルートテーブルにVPCに紐づくインターネットゲートウェイを繋ぐ

だいたいの概念解説

1. VPCを作る

f:id:y-iio:20180315151126p:plain

VPCてなに
デッカイ囲い(概念)だ

f:id:y-iio:20180315151231p:plain

2. サブネットを作る

さっき作ったVPC内にサブネットを作る

f:id:y-iio:20180315151432p:plain

アベイラビリティゾーンてなに
サーバたちは物理的に離れた場所に置いてあるんだけど、その置き場所区分のこと
アベイラビリティゾーンAで火事があってもアベイラビリティゾーンBのデータは無事だよ

f:id:y-iio:20180315153202p:plain

サブネットてなに
アベイラビリティゾーン内での囲い(概念)だ
どんどん囲っていくぞ
なぜこんなに区切るのかって?区切ってでかいものを小さく分けた方が取り回しやすいからさ
パブリックとプライベートの二種類があるのだけど、VPC外と通信する場合はパブリックにする

f:id:y-iio:20180315153213p:plain

3. ルートテーブルにVPCに紐づくインターネットゲートウェイを繋ぐ

ルートテーブルてなに
サブネット間や外部との通信用の設定

インターネットゲートウェイてなに
インターネット通信するぜ!それならこいつが必要さ
VPC外との通信用の玄関口

f:id:y-iio:20180315153223p:plain

さっき作ったVPCのルートテーブルに インターネットゲートウェイをルートとして追加する
さっき作ったサブネットも関連づける

f:id:y-iio:20180315151754p:plain

f:id:y-iio:20180315152424p:plain

これでいいかんじに外界ともつながった囲いができたよ
この囲いの中なら何だってやりたい放題だ!!!違う

f:id:y-iio:20180315153234p:plain

こうして出来上がったネットワーク内に
EC2インスタンスなどを配置していくんだね、ドラえもん!

f:id:y-iio:20180315153244p:plain

詳しい手順はこちらを参考に、、

qiita.com

Does your neural net need more data?

Hi! This is Chinnapa, from Goalist. Today I decided to write an English post, because we clearly have fewer of those than we need :).

When improving a neural net (or any machine learning algorithm) one question that inevitably comes up, is

Will the algorithm do better if I give it more data?

The thing is, very often gathering more data involves time, effort, and money. So it's probably a good idea to think carefully about it first. Accurately diagnosing whether you need more data, and what kind of data you should go about collecting, can save a lot of headache.

Under-fitted models

One thing to consider is whether your algorithm is under-fitting your data. Under-fitting is when the algorithm is :
- (a) not doing as well as you'd like (low accuracy or low f-score)
- (b) It is performing badly on both the training set, as well as the validation set, and the gap between these scores is relatively small.

In this case, gathering more of the same data is unlikely to improve your results significantly, if at all. However, increasing the input features may help. So, for example, if you're trying to predict the height of a person based on their age - you may want to collect other data for the data labels - such as weight. As opposed to getting more data of age -> height.

If, however, your data does already allow for a reasonable prediction, then the problem probably resides in the model, and not in the quantity of data. You can test this by considering if a human (equipped with the expertise) would be able to make predictions based on your input data.

For example, if your model is attempting to label a picture, and you have an under-fitting issue, increasing the size of the picture (more input features) is unlikely to help. The model should be able to label the picture with the data it already has. As discussed above, increasing the number of pictures is also unlikely to improve an underfitting issue, and your efforts would likely be best spend in trying different neural network models (more filters in a conv net, more layers etc.)

Over-fitted models

The opposite case is when your model is over-fitting your data. Overfitting is when your model does well on your training set, but does significantly worse on the validation set.

Here too, before deciding to gather more data, it would be wise to perform an error analysis first. Actually looking at each mistake that a model makes can help significantly. There may be some type of skew or bias in your training set Maybe you didn't shuffle the training and validation data? Maybe there are certain noise / signals that your model is picking up that are non-representative or don't make sense?

https://github.com/marcotcr/lime

Is one tool you can use to help you analyze why your model is making the decisions it is.

You also have two amazing tools that can emulate the effects of gathering more data:

Regularization

Regularization is a method that increases the loss of your model based on factors that are not related to accuracy. One example is using regularization to cause the magnitude of the weight matrices to contribute to loss. It prevents your model from trying to account for the peculiarities of anomalies that may (do) exist in your data.

Essentially it stops this:

f:id:c-pattamada:20180308115959p:plain

Dropout

Dropout layers are a simple an extremely effective tool that randomly ignore features in a layer of the neural net (during training only). This results in the model being unable to fixate on single features, and force it to use all possible information in the data to make predictions. Note that you'll have to increase the number of epochs the model trains for when you use dropout.

Here's what a simple net might look like in python/keras using the above features.

input_features = Input(shape=(num_features,))
processing = Dense(1024, activation='relu', kernel_regularizer=l2(0.01))(input_features)
processing = Dropout(0.5)(processing)
processing = Dense(1024, activation='relu', kernel_regularizer=l2(0.01))(processing)
processing = Dropout(0.5)(processing)
output = Dense(category_count, activation='softmax')(processing)
model = Model(inputs=input_features, outputs=output)

The kernal_regularizer parameter takes a regularization function that works to keep the weights on the layer from getting too large. l2() is one of the default regularizers that comes with keras, and it's parameter, 0.01 is the lambda multiplier (increasing it will increase regularization). Dropout(0.5) is a dropout layer that has a 50% chance of ignoring a specific feature. Dropout layers are only used during training, so they won't change hamper your model in production.

In summary

When evaluating your model and deciding how best to improve it, diagnosing what problem you're trying to solve under-fitting or over-fitting is the first step. This will guide you on whether you need to gather more of the same type of data, new features, whether data isn't relevant to your problem at all.

Next, in the case of over-fitting, experiment with regularization and dropout.

Finally, once you are convinced that your model is actually overfitting, and neither regularization or dropout has improved it sufficiently, then it is worth setting down the arduous road of gathering more data.

Best of luck!