TECH PLAY

株式会社LIFULL

株式会社LIFULL の技術ブログ

652

こんにちは、新卒入社1年目の椎橋です。普段の業務ではデータを予測したり、広告費を最適化したりと、データサイエンス業務を行っています。 今回は社内留学制度を利用して技術基盤部に留学してきました。社内留学制度とは、他部署に一定期間所属して業務をこなしながらスキルを磨いたり、新たな挑戦をしたりできる制度です。私は計算用サーバを使って大規模な計算ができるようになりたくて、その勉強のために留学しました。 技術基盤部は主にインフラの構築・監視・運用やレガシーシステムの刷新、他部署への技術支援などの非常に重要な業務を行っており、HOME'Sのサービスやエンジニアを支えている部署です。 留学で行ったタスクは、HOME'Sのウェブアプリケーションをサーバで動かすために必要なミドルウェアを洗い出し、ansibleを使用してサーバを構築することでした。 構成を理解する 構築してHOME'Sを動かす 感想 構成を理解する まずはHOME'Sが動作するために必要なミドルウェア及び各種設定内容などを調査し、理解する必要がありました。初めは何から進めればよいかもわからず、まさにゼロから始めるlinux生活でした。先輩に聴き、書籍やウェブページなどで調べて、関連するファイルを読みました。例えばhttpdを調べたときは、以下のように記述されていました。ただし、コメントアウト内容は実際のconfファイルには記述されていません。 $ view httpd.conf ... #サーバの基点ディレクトリ ServerRoot "/usr/local/apache2" #ポート番号を指定 Listen 80 ... それぞれの行で何を設定しているのかを調べていくと再び知らない言葉に遭遇し、それを調べて・・・というのを繰り返しました。 構築してHOME'Sを動かす AWSのインスタンスを新規作成し、調査した各種ミドルウェアのインストールや設定などを行い、HOME'Sのサイトが閲覧できれば一先ずOKなのですが、ここでも問題が起こりました。 下記のように、一つ一つコマンドを調べながらhttpdの設定を行っていきました。 $ sudo yum install httpd #httpdをインストール $ sudo chkconfig httpd on #httpdの自動起動設定 $ sudo /etc/init.d/httpd start #httpdの起動 この後、モジュールやバーチャルホスト、ドキュメントルートなどの設定を鈍足ながら行いました。しかし、あまり考えていなかったために元々のサーバと異なるバージョンのhttpdをインストールしていました。早く気づいていればNEW GAMEすることもできたのですが、すでに、ファイルの追加や書き換えをした後でしたので、作業済のファイルを残したままバージョンのみを変更しようと試みました。結果的にはバージョンの変更と共に設定すべき事項が多く、私では解決できなかったので、始めからやり直すことにました。バージョン確認は重要であることを痛感しました。 最終的な結果としては、なんとかHOME'Sをブラウザで表示できるようになったところで時間切れとなり、まだ設定すべき事項はあったのですが、完遂できませんでした。ansibleにも辿り着けず、当初の目標は達成できませんでした。 感想 タスクは終わりませんでしたが、コンピュータが苦手な私には良い勉強の機会になりました。独学では理解できなかった概念を身につけられたように感じます。私の本来の業務では、異常検知や最適化のプログラムを作成していますが、留学後にlinuxを触ってみたら、RやPythonの環境構築からcronで定期実行するまでできるようになりました。これで計算可能な問題が広がり、数理モデリングの制約が緩くなったような気がします。 挑戦したい人が挑戦できるような環境が社内に整っていることが伝われば幸いです。
アバター
こんにちは。おうちハッカーの石田@リッテルラボラトリーです。 みなさんは、 ReTech って言葉を聞いたことはありますか? おそらく聞いたことのあるFinTechは、Financial Technologyの略で、金融をITや情報技術で新しいサービスを生み出したり、既存の問題を解決する動きのことです。 ReTechは、 Real Estate Tech の略で、 不動産領域の問題をテクノロジーで解決する 動きのことです。 アメリカでは、FinTechは既に様々な分野で技術が導入され、レッドオーシャン状態になっているため、次に来るのはReTechだ!と言われております。 http://www.mckinsey.com/    *1 こちらは、各産業において、どの程度情報技術が入っているかを示した図となります。 金融、保険については、図の上の方でほとんど緑となっており、かなり技術が入ってきていることが分かります。 一方で不動産領域は赤や黄色ばかりで、まだまだITが入ってきていません。 実際に米国では、Real Estate Techに対する投資が増加しているそうです。 zuuonline.com *2 そこで先日、 FIT2016 第15回情報科学技術フォーラム@富山大学 で行われたイベント企画、 「Real Estate Tech:不動産×IT 〜ITが拓く不動産の未来〜」に参加してきました。 *3 今回は日本における不動産×ITに携わる、 大手不動産ポータル、スタートアップ、研究者たちが一堂に会したReTechの最先端技術 の発表の模様をお届けしようと思います。登壇者の方々はこちらとなります。 ビジネスサイドとアカデミックサイドそれぞれ3講演ありましたので、前編では、ビジネスサイドの3講演をご紹介します。 「HOME'Sデータセット」提供を通じた不動産領域におけるオープンイノベーション促進の取り組み トップバッターとして、弊社の清田から発表させて頂きました。 「あなたにおすすめの物件はこれ!」といった物件の推薦は弊社でも研究を行っていますが、不動産物件の推薦アルゴリズムはとても難しいことが分かっています。 本や服といった商品などとの違いとして、ユーザーがより時間をかけて選ぶこと、立地や性能などの条件が複雑であること、同じ物件は一つしかないことなどがあります。 また選択に時間をかけると、賃貸で考えていたが購入してもいいかもと変わったり、家賃が高くて希望の駅が変わったりします。 そのため、「 このお部屋を見ている人は、こんな物件を見ています 」が通用せず、協調フィルタリングなどの一般的な推薦アルゴリズムでは効果が小さいと考えています。 こちらは、住まい探し行動を可視化した図です。 最も単純な住まい探し行動は、検索→問い合わせ→来店→内見→契約、といった流れですが、 HOME'Sで検索した数日後に、物件名の検索でHOME'Sに帰ってくるパターンがあります。これはおそらく、HOME'Sを見て内覧して、別の物件を紹介されたが不安なので、物件名で検索してHOME'Sにたどり着いたというパターンと推測されます。住まい探し行動には様々なパターン・ストーリーがあり、有効な物件の推薦がとても難しいです。 また他の課題として、 長期にわたって影響する意思決定をどのようにサポートするのか 、ということがとても重要です。 住まい探しの選択は、数年から数十年に渡ってその本人や家族に影響を与えますが、選択の際には将来どのような問題に直面するか分かりません。 そのギャップをどのように埋めてあげるか、ということが重要になってきます。 このように人生に大きく影響を与える住まい探しは、 複雑な意思決定プロセスをたどるため、様々な分野の知見を集めて学際的に取り組む必要 があります。 そこでオープンイノベーションの取り組みとして弊社は2015年11月より、 「HOME'S」の物件・画像データセットを研究者に提供 しております。 ありがたいことに、国内・国外合わせて35の研究機関の方に使って頂いており、データセットを用いた研究も発表されつつあります。 研究分野は、情報学をはじめとして、建築学、経済学、都市学などさまざまな分野に及んでいます。 講演スライドは、こちらに公開しております。 「HOME'Sデータセット」提供を通じた不動産領域におけるオープンイノベーション促進の取り組み from Yoji Kiyota www.slideshare.net SUUMOでの分析事例と不動産データ活用の未来 野村眞平様、李石映雪様(株式会社リクルート 住まいカンパニー ) SUUMOを運営している株式会社リクルート 住まいカンパニーのご講演でした。前半は野村様から、SUUMOにおける今までのデータ分析の取り組みを紹介されました。 さまざまな取り組みをしており、特に東大の松尾先生との共同研究である、将来のCVRを向上させるための推薦アルゴリズムの研究が興味深かったです。 人は何かを選ぶとき、様々なものを比較検討して選んで初めて、納得感のある選択をすることができます。 例えば、1億円, 3000万円, 5000万円の物件を見て、5000万円の物件に決める、といったことです。 納得感のある家探しのために、不動産情報ポータルとしては、 幅広い選択肢をユーザーに提供すること が重要です。 直近の問い合わせされやすそうな物件を推薦すると、同じような物件ばかり出てきて、視野が狭くなってしまいます。 そこで 次の次に問い合わせがされやすそうな物件も含めて検討 することで、幅広い選択肢を提示し、将来的な問い合わせ率の向上を目指す研究を行ったそうです。 後半は、李様が現在進行している研究についてお話しされました。 SUUMOでは、実験的にユーザーと不動産会社が直接チャットできるサービスを提供しているそうですが、そのログを用いて チャットの応答と来店率の研究 を行っているそうです。 このように、どのやり取りが来店率に影響を与えているかを分析しています。具体的な日時の話題になると、かなり来店率が高くなっていることが分かります。 これらを分析を通して、 ユーザーに来店してもらうには、不動産会社はどのような応答を行えばいいのか、支援する仕組み を作っていくとのことでした。 他にも、リアルタイムな個人最適化レコメンドページ、画像解析などの取り組みをご紹介いただきました。 推薦システム、画像解析、自然言語処理など幅広い分野でReTechをリードしていらっしゃると感じました。 実践的! 人工知能×機械学習 iettyの場合 小川泰平様(株式会社ietty 代表取締役社長) iettyは、自分の住みたい部屋の条件を登録すれば、最適な部屋をプッシュしてくれる——お部屋“探され”サイトです。 現在、不動産取引を行う際には、 重要事項説明を対面で行わなければいけない 、という決まりがあって完全にオンラインにできません。 しかしこれを 2017年を目途に法律を改正し、オンラインでの契約ができるようになり 、ネット証券・ネット保険に続き、ネット不動産仲介の分野が成立する予定です。 iettyはいち早くトライアルの業者として、オンライン化を進めているスタートアップです。 現在、ユーザーとのやり取りにおいては、 人手によるものと人工知能の自動応答によるもののハイブリット となっています。 人手の案内では、案内したユーザーの 4.28% が部屋の内覧まで行きますが、あまり多くのユーザーを案内することができません。 一方人工知能の案内では、非常に多くのユーザーを案内することができる一方、推薦アルゴリズムの精度の低さから、わずか 0.07% しか内覧に行きません。 まだまだ人による案内にはかなわないのが現状です。 しかしながら、人工知能での推薦の質を向上させることができれば、より多くのユーザーが内覧・契約までたどり着き、収益を劇的に向上させられる大きな可能性があります。 そこでさまざまな手法を実装し、試しているのですが、ベンチャーならではのやり方で評価を行っているそうです。 学術の分野で推薦アルゴリズムの評価は、データセットを分割し、ROC曲線などで定量的に評価します。 しかしiettyでは、まずは実装してみて、 プロの目で判断、とにかくサービスに実装してみて評価という素早い動きでサイクルを回して評価・改善 を行っています。 すぐに実践投入という、とてもベンチャーらしいやり方で素晴らしいと思いました。 後半に続く ここまで、ビジネスサイドの事例を紹介しました。次回はアカデミックサイドの不動産関連研究について紹介します。 *1 : 本イベントを企画された東大・山崎先生が導入に使われた資料となります。 *2 : 同じく山崎先生が導入に使われた資料となります。 *3 : 近い日程でFIT2016という同名のイベントが行われたようです。もう一つのFIT2016は日本最大のFinTechのイベントだそうです。 http://www.nikkin.co.jp/fit2016/
アバター
こんにちは。技術基盤部の磯野です。 ちょっと間が空いてしまいましたが引き続きZipkinです。 今回は Ruby + Sinatra で動いている Webアプリケーションへのトレーサーの導入です。 前々回の記事 → Zipkinを導入してみた(サーバー編) 前回の記事 → Zipkinを導入してみた(PHP編) 構成 CompositeAPIでの処理の流れ RestAPIでの処理の流れ 処理の流れを追跡するためのリクエストヘッダ app.rbの設定 (CompositeAPI, RestAPI共通) monkey_patch/zipkin_tracer の実装 HTTP::Requestクラス用のzipkinトレース処理用メソッド 使い方 結果 終わりに 構成 Rubyのライブラリは公式の zipkin-tracer を導入します。 構成はこのような感じです。 画像のアプリケーション・フレームワーク → Zipkin Sinatra CompositeAPIでの処理の流れ トレースデータの初期化(trace_id, span_idはWebサーバーからのリクエストヘッダに設定されている) マルチスレッドで非同期にRestAPIを複数呼び出し、その際にトレースデータを記録し、追跡するための情報をリクエストヘッダに付与する トレースデータを集計しjson形式でzipkinサーバーにhttpで送信する RestAPIでの処理の流れ トレースデータの初期化(trace_id, span_idはCompositeAPIからのリクエストヘッダに設定されている) 各データベースや全文検索エンジンなどにリクエスト送信、必要に応じてトレースデータを記録する トレースデータを集計しjson形式でzipkinサーバーにhttpで送信する 処理の流れを追跡するためのリクエストヘッダ 前回の記事 で説明しているので詳細は省きますが、以下はそのHTTPヘッダとその説明です。 HTTP Header Type 説明 X-B3-TraceId 64 encoded bits *1 リクエストごとに共通のID、これで追跡情報を紐付ける X-B3-SpanId 64 encoded bits *1 計測ごとに一意に決まるID X-B3-ParentSpanId 64 encoded bits *1 直前の計測のSpanId X-B3-Sampled Boolean (either “1” or “0”) *2 サンプリング対象かどうか X-B3-Flags a Long - *1 内部データは数値ですが、ヘッダに付与する際は16進数表現した文字列に変換します。 詳しくは以下URLの「HTTP Tracing」を参照してください。 http://zipkin.io/pages/instrumenting.html app.rbの設定 (CompositeAPI, RestAPI共通) 以下のように ZipkinTracer::RackHandler を useするだけですが、マルチスレッドでは正常に動作しなかったので、パッチを当てています。 class Application < Sinatra :: Base configure do require ' zipkin_tracer ' require ' monkey_patch/zipkin_tracer ' use ZipkinTracer :: RackHandler , { server_name : ' composite_api ' , service_port : 80 , sample_rate : 0.0 , json_api_host : http :/ /zipkin.example.com } end end monkey_patch/zipkin_tracer の実装 モンキーパッチはこんな感じです。 アプリケーション自身のTraceを親としたトレース情報を作れるように設定 スレッドで動くようにMutexでの同期処理を追加 parent_idがnilの場合zipkinが例外を吐くのでnilの場合リクエストに含めない(v0.18.2で修正済み) Trace .module_eval do class << self remove_method :with_trace_id def root_id @root || self .id end def with_trace_id (trace_id) first = false @root ||= begin first = true trace_id end self .push(trace_id) yield ensure self .pop @root = nil if first end end remove_method :stack , :push , :pop def mutex @mutex ||= Mutex .new end def stack mutex.synchronize do @stack ||= [] end end def push (trace) mutex.synchronize do @stack ||= [] @stack .push(trace) end end def pop mutex.synchronize do @stack ||= [] @stack .pop end end end Trace :: Span .class_eval do alias_method :to_h_original , :to_h remove_method :to_h def to_h data = to_h_original data.delete( :parentId ) if data[ :parentId ].nil? data end end Trace :: ZipkinTracerBase .class_eval do remove_method :spans , :store_span , :reset def mutex @mutex ||= Mutex .new end def spans mutex.synchronize do @spans ||= [] end end def store_span (id, span) mutex.synchronize do @spans ||= [] @spans .push(span) end end def reset mutex.synchronize do @spans = [] end end end HTTP::Requestクラス用のzipkinトレース処理用メソッド zipkin-tracerにはfaraday-middlewareが付属しているので、faradayを利用している場合にはほとんどそのまま利用できます。 今回はHTTPクライアントとしてNet::HTTPを直接使っている為、リクエストクラスにヘッダを追加する処理とZipkinのトレースデータの登録処理をまとめて行うメソッドを定義しています。 module CompositeAPI class ZipkinTracer class << self def trace_with_http_request (req) trace_id = Trace .root_id.next_id b3_headers.each do | method , header | req[header] = trace_id.send(method).to_s end return yield unless trace_id.sampled? res = nil Trace .with_trace_id(trace_id) do local_endpoint = Trace .default_endpoint remote_endpoint = Trace :: Endpoint .make_endpoint( ' 0.0.0.0 ' , 80 , ' restapi ' , local_endpoint.ip_format) Trace .tracer.with_new_span(trace_id, req.method.to_s.downcase) do | span | uri = URI .parse(req.path) span.record_tag( Trace :: BinaryAnnotation :: URI , uri.path, Trace :: BinaryAnnotation :: Type :: STRING , local_endpoint) span.record_tag( ' http.query ' , uri.query.to_s, Trace :: BinaryAnnotation :: Type :: STRING , local_endpoint) span.record_tag( Trace :: BinaryAnnotation :: SERVER_ADDRESS , ' 1 ' , Trace :: BinaryAnnotation :: Type :: BOOL , remote_endpoint) span.record( Trace :: Annotation :: CLIENT_SEND , local_endpoint) res = yield span.record_tag( Trace :: BinaryAnnotation :: STATUS , res.code.to_s, Trace :: BinaryAnnotation :: Type :: STRING , local_endpoint) span.record( Trace :: Annotation :: CLIENT_RECV , local_endpoint) end end res end def b3_headers { trace_id : ' X-B3-TraceId ' , parent_id : ' X-B3-ParentSpanId ' , span_id : ' X-B3-SpanId ' , sampled : ' X-B3-Sampled ' , flags : ' X-B3-Flags ' } end end end end 使い方 req = Net :: HTTP :: Get .new( ' http://restapi.example.com/path/to/resource?key=1 ' ) CompositeAPI :: ZipkinTracer .trace_with_http_request(req) 結果 以下の赤で囲った部分が今回の作業により記録されるようになります。 終わりに zipkin導入に関しては一旦以上で終わりになります。 今回、WebSite, CompositeAPI, RestAPIの3層構造のアプリケーションにzipkinを導入しましたが、普段見れない各サービスの積み重ねの部分が視覚化できた事はとても有意義でした。 軽く見ただけでも、以下のような問題に気付く事が出来ました。 各APIやミドルウェアの呼び出しでどこがボトルネックになっているか(視覚的に認識できる) CompositeAPI → RestAPIの部分で並列にリクエストを投げられるところで直列で行っている CompositeAPI → RestAPIの呼び出しを無駄に行っていた(キャッシュでごまかしていた為初回のみ遅い) まだ各サービスの改修には至っていませんが、これらを一助としてサイトの高速化やマイクロサービス化を推進していけそうです。
アバター
こんにちは。 ホームズくんを描いたりしている"ママデザイナー"のモリです。   入社6年目。昨年出産をして、この4月に復職しました! 出産してもデザイナーとして働ける環境があることだけで、本当にありがたや、ありがたやですね。 そして、この夏。 3週間(週2日)在宅ワークしてみました!   在宅ワークをしてみて良かったこと、困ったことをお伝えします。     そもそもなぜ在宅ワークするのか もともと、子どもは4月から保育園に預けていたのですが、転居のため保育園も転園に。   転園先が決まっても、じゃあ初日から9h(8:00~17:00)保育お願いします! ...というのは子どもも保育園も大変ですよね。   なので、どの保育園でも基本的には保育開始日から5日前後は慣らし保育期間を設け、1日数時間ずつ保育の時間を増やしていき、徐々に9hの保育に慣れるようにします。 つまり、その期間通常の通勤、勤務ができなくなります。 なので、会社のありがたい制度を利用して、週に2日在宅ワークをすることになりました。 (弊社では現在週2日が最大です)     まずは業務環境 勤務時間 9:00~16:00(休憩1h含む) 子どもは保育園に預けてあります。 PCは会社から貸与されたノートPCとiPadPro(&applepen) 社内メールは見れます。 社内環境アクセスできます。 skypeMTGできます。 adobe系ソフト使えます。 ちょっとしたやりとりはChatworkで 基本的に問題なく業務はできました!不便だと思うこともほぼなかったです。 この環境を整えてくださった方々に感謝。   やってみて良かったこと すっぴん可(社会人は礼儀程度のお化粧はするものと教わりました) 裸足で良い 空調が思いのまま 声をかけられたり電話もならないので音楽を聴きながら作業ができました。 考えることに集中できました。 休憩時間で自炊できるので、節約に。 通勤時間がなくなるため、朝の準備、夕飯の買い物・支度に余裕ができました。 子どもを預ける時間が2h減って、いつもより長く一緒にいられました。 子どもの急な熱などによる保育園からのお迎え要請にもすぐに対応できます。   やってみて困ったこと 貸与されたPCはデザイナー用ではないのであまり解像度もよくないのと、 色もうまく見れない。 (PCを変えるorディスプレイの調整をすればいけるかも?) 社外秘を取り扱うことになるので印刷ができず、印刷ものの色がわからない。 貸与されたPCはデザイナー用ではないので、基本のフォントしかインストールされていない。 (デザイナー在宅ワーク用PCがあればよいかも。) ちょっと言えば、ちょっと見せればわかることを 文章にして伝えるのが面倒くさい 寂しい オフィス、チームの空気がわからない。     まとめ まずは働く人として。 私はデザイナーはやはりコミュニケーションが大切だと思っているので、 「毎日在宅ワークで」 というのはコミュニケーションに時間がかかるため厳しいなと感じました。 また、チームの中での連携という部分でも難しい点は多くあると思います。   後輩の育成に関しても、注意したり、ほめたりというのは その場にいるからこそできることだと思うので、この点にも在宅ワークの課題はあると思います。   しかし、週に数日という条件であればコミュニケーションの部分も大きな負担ではないと思いますし、 むしろ限られたコミュケーションの時間でいかに正確に伝えるかということも工夫せざるを得なくなるので、 効率が良くなる部分もあると思います。   また作る人として、考えることや手を動かすことに集中できる環境があるというのは とても良いと感じました。 (これは頑張ればオフィスでもできるかもしれないですが、なかなか難しいですね。)   最後に母としてですが、 通勤の時間(2時間強)がなくなっただけで、朝夕のバタバタがなくなり、 時間と心にだいぶ余裕ができたというのが正直な感想です。 心に余裕が生まれると、良いアイデアが!、、、、 とは言い切れませんが、仕事にも子育てにも良い効果はあるかと思います。   もしこの2時間が余裕としてあるのであれば、1時間は業務時間として増やせるかもしれませんし、 そのまま子供と触れ合う時間として残しておくのも良いかもしれません。 1時間早く帰れれば、子供の通院などもだいぶ楽ですね。   在宅ワークになると現状のような時間給が適切なのかなど、 いろいろ検討すべき点は多くあると思いますが、 働くママにとって在宅ワークは本当に救いの手になりそうです。    
アバター
  こんにちは。 HOME'Sアプリのデザイナーのこばやしです。   Androidアプリを育てていくと、ひとつの課題に行き当たります。 アプリリソースサイズです。   機能追加、ダイナミックな画像表現などで、気づいたら「ゲームアプリ?」と思うほどリソースサイズが増えているかも…。 そんな時、ひょっとしたら劇的にスリム化できるかもしれない方法をご紹介します。 HOME'S Androidアプリでも実際にやった内容です。 ==== Google deveroparsの記事「 Google Play におけるアプリのダウンロード サイズの削減 」に記載もある WebP が今回紹介する内容です。 googledevjp.blogspot.jp   記事の一文に、 3. APK の構成要素のサイズを減らすことによる最適化: たとえば、JPEG ではなく WebP を使用するなど効率的なファイル形式を使ったり、未使用コードを削除するために Proguard を使用したりします。 とあります。   記事にもあるように、インストールする際にアプリサイズが大きいと通信量を気にしてしまい、それが要因で優れたアプリでもインストールされない、なんてこともあるかもしれません。 そこで今回、画像リソースをWebPに変換することでどのぐらいアプリリソースを削減できるのか。 そしてHOME'S Androidアプリにおいて、実際どのぐらいリソースを削減することができたのかをお話します。 webP(Weppy=ウェッピー)とは Googleが開発した圧縮形式で、従来の形式よりもファイルサイズを小さくすることを目的としています。 Googleが持つVP8コーデックを用いたWebMという動画フォーマットをベースとしており、WebMの1フレームだけを切り出したものがWebPで、それをRIFFという軽量なコンテナに格納した形式になっています。 https://developers.google.com/speed/webp/   特長 可逆 / 非可逆圧縮が可能 透過 (アルファチャネル) が可能 写真の圧縮にも向いている アニメーションが可能 写真画像においても効果的に圧縮できるのが非常に強い特長だと思います。 ※非可逆のWebPはAndroid OS 4.0以降でサポート、ロスレス圧縮のWebPは4.2.1以降でサポート   サポート Chrome Opera (12.0~) Android Browser (4.2~) Chrome for Android JPEGやPNGといったメジャーな画像保存形式のようにはまだ普及しておらず、現段階だとかなり限定的に効果を発揮する形式だといえます。 http://caniuse.com/#feat=webp   ツール WebP Library Pixelmator Leptonica Photoshop Plugin WEBPコンバーター 公式のライブラリ、オーサリングツールなどで生成できます。 比較 アプリ内で実際に使用しているPNG画像、それをWebP化した画像で比較してみます。 ※WebPは表示させるためにブラウザで表示したものを撮影しています。容量はWebPのものを記載 WebP 2.88KB png 6.73KB このポーズのホームズくん、可愛い。 小さめのイラストですが、およそ半分に削減できています。 見栄えも変わりありません。 次は写真、複雑なビットマップ画像で試してみます。 WebP 27.4KB PNG 560KB 先程のイラストより高い圧縮率となりました。 肉眼ではほとんど区別つかないですが、およそ1/20のサイズに…これはスゴい。 実際にアプリで見てみます。 before after 意図したとおりに表示されてます。 大丈夫そうです。   アプリで使っている画像をどんどん置き換えてみる   Android studioのAnalyze APKを使い、容量が大きい画像をWebPに変更してみました。 すると… 13.2MBから6.3MBとおよresの 容量が半分に。 半分です。 ※2016年8月時点 画像リソースはアプリ全体の半数以上を占めていましたが、WebPを用いることで簡単に削減すること成功ができました。 画像の品質は下げたくない、けれど容量を使いすぎるのも…という課題に対しても効果的です。 アプリの表示速度や低スペック端末への配慮としても、一役買ってくれそうです。 まとめ 可愛い名前なのにスゴいやつ! iOS対応やブラウザの対応拡大が待ち遠しい。 実は以前にもWebPを試したことがありました。 しかし当時は挙動が安定していなく使用を断念しました。 最近は4.x系でもSVGをフルサポートするなど、Androidアプリ開発環境がグングン良くなっています。 そんな中で改めて試してみたWebPはAndroidアプリでリソースを削減する手段としてとてもおすすめです。 「 Android Appにおいて、かつサポートしているOSバージョンが4.1.x以上の場合はおすすめ 」といえるのではないかと思います。 ですが、これから普及していくであろう新しい規格のため、考慮すべき点もあります。 「WebPとは」のところで記載してある、サポート範囲と特長のAndroid OSバージョンによる制約を改めて確認し、上手に利用してみてください。
アバター
   はじめまして!新卒入社1年目のミーコです。 初めてデザイナーズブログを書きます!よろしくお願いいたします。 今回は「ネクストのデザイナーってどんな人がいて、どんなことしてるんだろう?」や「新卒のデザイナーってなにするの?」というような就活セミナーや面接では聞けないであろう情報も含め、新卒1年目から見たネクストデザイナーの1日をモリモリ紹介いたします!   まずは私の自己紹介から。 3月に大学を卒業し、4月に株式会社ネクストに入社しました。社会人1年目のひよっこデザイナーです。 ネクストに入社を決めたのは〜・・・長くなるのでやめておきますが人に喜んでもらえるようなデザイナーになりたいと常に思いながら日々、業務をしております。   ざっくりと1日を紹介すると です!本当にざっくりですね。でもこんな感じです。 それではこれから細かく紹介していきますねっ!   出社 始業開始は10時です。 10時に会社にいれば早く来てもゆっくりきても大丈夫です。 出社後は1日のタスク・メールを確認し、お仕事スタート!    仕事(午前) 入社5ヶ月目ですが、今までやってきた仕事は 広告やバナーの制作 民泊事業に関するインフォグラフィックスの制作 ホームズくんを使用したイラスト制作 ▼例  竹うちわのデザイン ラッピングバスのデザイン ▼例 ビーチサンダルのデザイン などなどです。これはほんの一部なのでさらに書き出せばもっともっと色んなことしてますヨ。   自分がデザインしたものが世に出ていると思うと嬉しいですよねっ! ネクストデザイナーは1年目からこんな嬉しい経験ができますよ〜^^☆   デザインをする上で ・ラフ案は最低3つ以上出す ・何のために、誰のために作るのかを考える を大事にして制作しています。   ラッピングバスをデザインする時は、 いつ・どこで・なぜバスを走らすのか、それによってどうなるべきなのかを考えたり、バスを乗る人の気持ちになってデザインしました。 わからないことがあればいつでもグループの先輩や、周りの方に助けてもらっています。 丁寧に指導してくださるネクストの社員の皆さんは本当に優しいですよ〜^^☆   お昼休み デザイナーやエンジニアのものづくりメンバーは基本社内にこもっているのでお昼休みが唯一デスクから離れて外に出るチャンスです! コンビニで買って食べることもありますが、外に食べに行くことが多いです! 同期・先輩や、お世話になった採用人事の方、なんと秘書の方ともランチに行けます! 品川のランチを制覇することが今期の目標です。  定食や~ お肉料理など~ 肉・魚・米・うどん・そば・ラーメン・パスタなど食べたいものは品川には揃っているので毎日美味しいものを食べられます。幸せです。 昼休みはちゃんと1時間取れますよ〜^^☆   仕事(午後) お腹いっぱい〜になったところで午後の仕事スタートです。 午前中にやっていたことの続きだったり、ミーティングが入っていたりなど19時まで業務をこなしています。 あっ、15時になったら会社にくる郵便を社内の人に配達しています。これも新卒の重要な任務です! 社内の人の顔と名前を覚える&覚えて頂くチャンス!今ではすっかり配るスピードも速くなりました!   退社 新卒は残業しちゃダメと言われているので19:00になったら帰っても大丈夫です。 入社前の勝手なイメーシでは遅くまで仕事してるんだろうな〜と思っていましたが、そんなことはないはずです。 これはあくまで新卒デザイナー個人の意見なので、わかりませんが・・・・ 私は19時過ぎたらきりの良いところで作業はやめて、日報を書き20時には退社できるようにしています。 帰宅してコーディングの勉強(通称:地獄のcodingトレーニング)に励んでいます。   こんな1日です。いかがでしたか??   伝えたいことは3つ!   新卒1年目からジャンルにとらわれないものづくりができる ネクストは優しい人が多い お昼においしいご飯がたべられる  以上です。   最後までご覧頂きありがとうございましたっ 次回の更新ではちょっと特別な1日を紹介しちゃいます!お楽しみ! では!  
アバター
はじめまして、技術基盤部の相原( kaihar4 )です! 今回は、アプリケーションのクラウドサービスへの移行の一環で、 Amazon S3から取得した画像URLを含むファイルを元に、そのURLの外部画像を取得して返す機能 を mruby で書き直してAWSに移行した話をしていきたいと思います。 この機能は元々モノリシックなアプリケーションの一機能として動いていたもので、これを切り出してAWSに移行するというのが今回私に与えられたミッションでした。 このアプリケーションは歴史が長く、その間ほとんどメンテナンスされていませんでした。 ディストリビューションは古くPHPのバージョンも4系、したがってそのまま持っていくという選択肢はなく、AWS上に新規にインスタンスを構築することになります。 弊社にはAPI部分をPHPからRubyに移行する方針があるということもあり、Amazon Linux上にRubyで書き直したこの機能を移行するというのが妥当な線でした。 しかしアプリケーションの性質上Unicornはプロセスモデル的に適さないですし、そもそもこれだけの機能のためにアプリケーションサーバを用意するということにも違和感がありました。 そこであがってきたのが、 mruby でこの機能を実装し ngx_mruby で動かすという選択肢です。 mruby であればRubyと(ほぼ)同じシンタックスで実装することができ、それを ngx_mruby で動かすことでウェブサーバがそのままアプリケーションサーバとして振舞うことができます。 開発者を多く確保できる mruby と弊社での運用実績があるnginx、これらを使う旨を運用チームへ相談の末、このプランで行くことに決まりました。 このように置き換わるイメージです。 元々キャッシュをするように作られていなかったので、この機会にRedisによるキャッシュも入れました。 ロゴ: Amazon S3 , redis ここからは mruby と ngx_mruby についてと、いかにこれらでこの機能を実装したかについて書いていきます。 本エントリを通してmruby + ngx_mrubyでアプリケーションを実装するという選択肢の現実味を感じていただければと思います。 mrubyとは ngx_mrubyとは mruby + ngx_mrubyでアプリケーションを実装するには YAMLから情報を取得する クエリストリングを元にAmazon S3からファイルを取得する 取得したURLをRedisにキャッシュする 取得したURLにリクエストして画像を取得して返す まとめ mrubyとは mruby とは ISO を元に実装されたRuby1.9互換のシンタックスを持つ組み込み向けの軽量言語です。 様々な分野に活用事例があり、ウェブの領域でも mod_mruby や ngx_mruby などで利用されています。 最近では h2o に採用されたことも記憶に新しいですね。 この言語の最大の特徴は軽量言語ゆえの省メモリな設計です。 mruby 本体には必要最低限の機能しか実装されておらず、例えばファイルの読み書きやHTTPのリクエストなどはサポートされていません。 これが組み込み向けとされる所以で、これのお陰で非常に少ないメモリで動作することが可能です。 そして、この必要最低限の機能を支える仕組みがmrbgemsです。 mrbgemsとはRubyで言うところのRubyGemsにあたるもので、有志が mruby にない機能を実装しmrbgemsとして多数公開しています。 このC言語または mruby 自身で書かれたmrbgemsを mruby と共にコンパイルすることで、それらが起動時に読み込まれ、その機能を利用できるという仕組みです。 mgem-list に登録されたmrbgemsであれば、 mruby 側が自動で依存関係を解決してくれるという強力な仕組みも備わっています。 これらを利用することにより、 mruby には一般的なプログラミング言語と遜色ない機能が実現されているのです。 ngx_mrubyとは 次は、先ほど mruby の活用事例としても紹介した ngx_mruby です。 ngx_mruby は、nginx上で mruby を実行できるようにするnginxの拡張です。 同じく先ほど活用事例として紹介した mod_mruby はこれをhttpdで実現したものとなります。 ngx_mrubyを使うことで、以下のようにnginx内で mruby を実行することができます。 location / hello { mruby_content_handler_code ' proc = Proc . new do | env | [ 200, { "Content-Type" => "text/plain;charset=utf-8" }, ["Hello World" ] ] end run proc '; } これらを使って mruby でウェブサーバの設定ファイルを記述することで、他の mruby を実行できるウェブサーバと設定を共有することができます。 秘伝のrewriteルールなども mruby で記述することによってウェブサーバ間で使い回すことができ、さらにはテストコードを書く事で保守しやすいものへとリファクタリング可能です。 このウェブサーバ上で mruby を実行できる仕組みを使ってアプリケーションを実装するというのが今回の主題です。 mruby + ngx_mrubyでアプリケーションを実装するには さて、ようやく本題です。 今回実装する機能の要件は以下の通りです。 アプリケーションを実装する際によくある要件だと思います。 YAMLから後述のRedisに接続するための情報を取得する 与えられたクエリストリングを元にAmazon S3からファイルを取得する Amazon S3から取得したファイルからURLをパースする そのURLをRedisにキャッシュする そのURLにリクエストして画像を取得して返す これらをmrubyでどうのように実現するのか順に追っていきましょう。 YAMLから情報を取得する アプリケーションを開発する際には、大抵設定ファイルを読み込んでRDBMSなどへの接続情報を得るといったことが必要になると思います。 これを mruby で実装するとどのようになるか見ていきましょう。 これは以下のような処理で実現することができます。 YAML .load( File .open( ' /path/to/yml ' ).read) 使用しているのは以下のmrbgemsです。 mruby-yaml mruby-io mruby-yaml では YAML.load_file は実装されていないため、 mruby-io で File.open と IO#read を使っていますが、Rubyでも動く完全Ruby互換のコードとなっています。 ただ、これをRedisに繋ぐたびに実行するのはio的にコストなので、初回だけの実行にしたいところです。 しかし、 ngx_mruby ではリクエストごとに mruby のオブジェクトが初期化されてしまいます。 そこで使うのが mruby-userdata という、mrb_state構造体を介してオブジェクトを mruby プログラム間で共有するためのmrbgemsです。 初回に mruby-userdata を使用して接続情報をmrb_stateに入れておき、以降はそこから取り出すことで無駄な処理をなくすことができます。 ngx_mruby には mruby_init という起動時にのみ実行されるディレクティブがあるので、以下の処理を記述したファイルを指定することでこれを実現することができます。 mruby_init /path/to/init.rb; server { } # init.rb config = Userdata .new( ' config ' ) config_file = YAML .load( File .open( ' /path/to/yml ' ).read) environment_config = config_file[ ENV [ ' ENV ' ]] config.redis = environment_config[ ' redis ' ].map {| k , v | [k.to_sym, v] }.to_h mruby-env を使えば、 ENV 定数によって環境変数を取り扱うことができるので、環境変数によって読み込む設定を切り替えるといったことも可能です。 環境変数は単純に /etc/sysconfig/nginx から渡すことができます。 # /etc/sysconfig/nginx export ENV=production クエリストリングを元にAmazon S3からファイルを取得する 次はAmazon S3へリクエストを投げる部分です。 ngx_mruby では rack-based-api を採用しているので、以下のようなファイルを mruby_content_handler ディレクティブに指定することで mruby を実行することができます。 末尾の cache をつけると mruby のコードをnginxがキャッシュするようになります。 location /hello { mruby_content_handler /path/to/client.rb cache; } # client.rb class Client def call (env) end end run Client .new Kernel.#run に渡すオブジェクトは #call メソッドを実装している必要があるのでProcオブジェクトでも可能です。 そして、その #call メソッドの引数として得られる env オブジェクトにクエリストリングをはじめとした情報が格納されています。 env['QUERY_STRING'] に丸ごと入っているので以下のようにパースすると扱いやすいです。 # client.rb class Client def call (env) params = env[ ' QUERY_STRING ' ].split( ' & ' ).map {| kv | kv.split( ' = ' ) }.to_h end end run Client .new 次にAmazon S3に繋ぐ処理ですが、今回はAmazon Linuxを使用しているため、IAM RoleからAccess Tokenを取得してきてそれを使いたいところです。 http://169.254.169.254 からHTTPで取得するため、 mruby-simplehttp を使います。 またこれも同様に毎回取得する必要はないので、先ほどの mruby-userdata を使って init.rb で初回時にのみ実行するようにしましょう。 IAM Roleの名前は可変なので mruby-env を使って ENV 定数により環境変数から与えることにしています。 # init.rb . . . metadata = Userdata .new( ' metadata ' ) metadata.iam_role = ENV [ ' IAM_ROLE ' ] json_credentials = SimpleHttp .new( ' http ' , ' 169.254.169.254 ' , 80 ).get( " /latest/meta-data/iam/security-credentials/ #{ metadata.iam_role }" ).body metadata.credentials = JSON .parse(json_credentials) # /etc/sysconfig/nginx . . . export IAM_ROLE=remote_image mruby にはもちろん標準でjsonモジュールはありませんので、レスポンスのjsonのパースにはmrbgemsを使います。 類似のmrbgemsが多数存在しますが、ここでは mruby-iijson を使っています。 あとはここで取得したクレデンシャルを用いてAmazon S3にリクエストするのみとなります。 init.rb で起動時に mruby-userdata に入れてあるので取り出してリクエスト時に使用します。 Amazon S3へのリクエストにはちょうどいいmrbgems、 mruby-aws-s3 があるのでこれを使いましょう。 #3 にてIAM Roleから得られるSecurity Tokenに対応したので今回のようなパターンでも利用することができます。 便宜上、先ほどパースしたクエリストリング内にAmazon S3から取得する 画像URLを含むファイル へのパスが含まれているものとします。 # client.rb class Client def call (env) params = env[ ' QUERY_STRING ' ].split( ' & ' ).map {| kv | kv.split( ' = ' ) }.to_h metadata = Userdata .new( ' metadata ' ) credentials = metadata.credentials s3 = AWS :: S3 .new(credentials[ ' AccessKeyId ' ], credentials[ ' SecretAccessKey ' ], credentials[ ' Token ' ]) response = s3.download(params[ ' path ' ]) end end run Client .new これでAmazon S3から 画像URLを含むファイル を取得することができました。 ここでの注意点として、初回時にのみクレデンシャルを取得するようにしていると、これらのクレデンシャルが期限切れになった場合に対応することができません。 Access Key IdもしくはSecret Access Keyが異なっている場合は 400 が、Tokenが異なっている場合は 403 が repsponse.code として得られるのでクレデンシャルの再取得の処理が必要です。 取得したURLをRedisにキャッシュする Amazon S3から取得した 画像URLを含むファイル はjsonなので、ファイルから外部画像のURLをパースする処理は、先ほどと同じ手順で response.body をパースするだけなので割愛します。 ここではAmazon S3へのリクエスト数を減らすためにRedisでキャッシュを行います。 これもよくあるパターンですが、もちろん mruby でも実現可能です。 これには mruby-redis を使います。 接続情報は先ほど init.rb にて取得してあるのでそれを使います。 # client.rb class Client def call (env) . . . config = Userdata .new( ' config ' ) redis = Redis .new(config.redis[ :host ], config.redis[ :port ]) redis.set(key, target_url) end end run Client .new 実際にはRedisのキャッシュの有無を確認してAmazon S3へリクエストを送るかどうかを判定する必要がありますが、ここでは割愛します。 今回はRedisにAmazon ElastiCacheを利用していてバックエンドのRedisが複数台いるため、負荷分散のために都度コネクションを張っていますが、特にそういった事情がない場合は、Redisのコネクション自体を mruby-userdata で共有して使いまわすことでコネクション開始時のオーバーヘッドを無くすことができます。 取得したURLにリクエストして画像を取得して返す 最後の処理です。 HTTPのリクエストを送るために、先ほどクレデンシャルを取得するのに使用した mruby-simplehttp を使います。 またこの例では、 mruby-http を使用してクエリを組み立てています。 ngx_mruby が採用している rack-based-api では、 Kernel.#run メソッドの引数に与えるオブジェクトが #call メソッドを実装している必要があることに加え、レスポンスとして返す #call メソッドの返り値が以下の例にあるような status code 、 header 、 body を含んだ配列でなければならないという制約があります。 # client.rb class Client def call (env) . . . uri = HTTP :: Parser .new.parse_url(target_url) request_query = uri.query ? "#{ uri.path } ? #{ uri.query }" : uri.path response = SimpleHttp .new(uri.schema, uri.host, uri.port).get(request_query) unless response.code.to_i == 200 return [ 404 , { ' Content-Type ' => ' text/plain;charset=utf-8 ' }, [ ' not found ' ]] end [ 200 , { ' Content-Type ' => ' image/jpeg ' , ' Content-Disposition ' => ' inline ' }, [response.body]] end end run Client .new このように配列をメソッド内で返すことで、ついに取得した画像をレスポンスとして返すことができました。 長くなりましたが、以上でこのアプリケーションのおおまかな処理は完成です。 まとめ このように、軽量言語の mruby でも強力なmrbgemsを駆使することで一般的なプログラミング言語と遜色ない処理を実行させることができました。 言語自体の単純な実行速度はRubyと比べると一長一短 *1 で単純にどちらが早いとは言い切れませんが、より少ないメモリで動作し、別途アプリケーションサーバを必要としない mruby の採用は一考の価値がありそうです。 弊社ではすでにこのアプリケーションが本番環境で動いており、200万req/dayを受けながら安定稼働しています。 mruby でこういったアプリケーションを書くことの是非は今後の運用を通して判断していきたいです。 *1 : RubyではC言語で実装されていたメソッドがmrubyだとmruby自身で実装されているケースがあり、その場合はmrubyの方が実行速度が遅い
アバター
こんにちは!新卒入社2年目デザイナーのカンバラとタカラベです。 2人とも、HOME'Sのサイト改修やノベルティの制作などをしております。デザインテクニックと合わせて、不動産業界の動向も日々勉強の毎日です! そんな中、DIYに詳しい先輩デザイナーにお誘いいただいて、人気に火がついていると噂の『カスタマイズ賃貸』で最先端をいく賃貸マンション「 ロイヤルアネックス 」にご訪問させていただきました。 カスタマイズ賃貸?ロイヤルアネックス? 「 ロイヤルアネックス 」とは、東京都・豊島区にある13階建ての賃貸マンションです。 単純に広さや設備の部分を見ると一般的なマンションとほぼ同じです。が!実際は満室状態が続いており、部屋によって入居待ちが出ているほど! 「な、なぜ賃貸マンションに入居待ちが!?」 人気の秘密のひとつには、『カスタマイズ賃貸』のマンションだということでした! カスタマイズ賃貸とは、注文住宅や新築だけでなく、賃貸でも居住者が部屋の壁紙や床材などを自由にカスタマイズできるお部屋のことです。 そんなロイヤルアネックスでカスタマイズ賃貸を仕掛けたのは、株式会社メゾン青樹の青木純さん。 実は、以前弊社で中古マンションの敏腕事業責任者として名を馳せていた方で、退職後にご実家の賃貸マンションを引き継がれたそうです。 賃貸マンションでも、もっと暮らしを楽しめる人を増やしたい。 そのために、壁紙を選べるようにしよう。 青木さんの想いが、今のロイヤルアネックスの原点だったそうです。  これが賃貸!?カスタマイズ賃貸の紹介 青木さんをはじめ、ロイヤルアネックスの方々にたくさんの素敵なお部屋を見学させていただきました! 今回は、私たちが特に興奮したカスタマイズ賃貸を2部屋ピックアップします。 かっ可愛すぎる!!これなら私もできるかも!サラさんのお部屋 1部屋目は株式会社メゾン青樹の新入社員である、サラさんのお部屋をご紹介します!  サラさんのお部屋は、ビビッドな黄色と青の原色に彩られた壁と、「額縁柄」の壁が絶妙な調和をみせております。 ベッド正面に貼られたいろんな形の「額縁柄」の壁紙には、ところどころスケッチや小物類が飾られ、本物の「額」のような役割を与えられています。 冷蔵庫の扉や本棚の側面に黒板塗料を吹きかけており、チョークで字や絵が描けるようになっているのも素敵でした。 驚くべきことに、壁紙や床材はサラさんご自身が貼ったそうです!どこで材料を仕入れたのかも優しく教えてくださり、「なんだか私にもできそう!」と思わせてくれたお部屋でした。 ちなみに、ご入社されたきっかけは何だったのでしょう?同じ新卒入社の身として気になり、こっそり伺ってみました。 大学時代にまちや地域に興味を持ち、 活動している中で青木さんと出会いました。 リノベーションスクールへの参加を通して、青木さんの取り組みに関わりを持ちはじめ、その後、入社を誘ってもらいました。 「ほしい暮らしをつくること・人やまちとつながりのある暮らし方」がここでならできるのではと思って、入社を決めたんです! なんて素敵なのでしょう... そんなサラさんは、会社と自分の部屋が同じ建物にあるため、通勤はエレベーターで30秒。Instagram「 30秒通勤女子の日常 」で日々の暮らしを発信されています。是非ご覧ください! 全てオーダーメイド!ルーム名は「KOJAK」 ロイヤルアネックスには壁紙だけでなく、間取りも自由に変えてしまう「オーダーメイド賃貸」のお部屋もあります! なんと、隣り合ったワンルームが2部屋空いたのがきっかけで、仕切っていた壁を壊して、1部屋に繋げてみたそうです! そのため、こちらのお部屋は玄関が2つあり、お邪魔する前から驚きでした!(写真が残っていなくてごめんなさい…) 内装も入居者の方のセンスが光る素敵さ。鮮やかなタイルの敷き詰められたキッチンや、ステンドグラスのついた押入れ収納が、大人のオシャレな空間を作り出していました。  カスタマイズ賃貸の魅力 皆さん、ロイヤルアネックスのカスタマイズ賃貸はいかがでしたでしょうか? 見学した私たちは、1つ1つの部屋がアトラクションのように見えて、それはもう、わくわくしっぱなしでした! なんといっても、 どこにでもあるごく普通の小さくて真っ白な部屋が、 少し手を入れるだけでその人オリジナルの空間になること 。 賃貸マンションに持っていた固定概念が、崩れていくような衝撃でした。 意外とカスタマイズは簡単にできる カスタマイズ賃貸に興味を持った人の最初のハードルは、「やってみたいけど、手間がかかる」ではないでしょうか。 賃貸マンションを自分好みのお部屋にするには、お金も時間も、手間もかかると思いがちです。 しかし、今回の訪問でお話を伺ったところ、貼ったり剥がしたりできる壁紙や、床に乗せて組み合わせるだけでできる無垢の木を使った床材なども増えてきたそうです! こういった手軽な材料も増えてきたことにより、カスタマイズへのハードルが 一気に 下がっているそうですよ! HOME'Sができること 今回、私たちはロイヤルアネックスに訪問して、カスタマイズ賃貸の魅力、そこに住む人々の幸せそうな暮らしかた、大家さんの熱い想いを肌で感じることができました。 HOME'Sは住まい探しのポータルサイトであり、均一で精度の高い物件情報を多くのユーザーに届けることを目指しています。 しかし、それだけではなく、ロイヤルアネックスのような魅力的で新しい暮らし方も提案していきたい!そう思わせてくれる場所でした。  そのためには、まずカスタマイズ賃貸というもの自体を多くの人に知ってもらう必要があります。少しずつではありますが、下記のようなキャンペーンを通して、カスタマイズ賃貸への取り組みを始めております。 www.homes.co.jp ※2016年7月12日現在、キャンペーンは行っておりません。  HOME'Sは、今後も住まいについて様々な取り組みを行っていきます!ぜひご期待ください!  ロイヤルアネックスの中にある飲食店「 都電テーブル 」にもお邪魔し、美味しいご飯をお腹いっぱいいただきました! 最後には青木さん、サラさん、見学者で集合写真を撮りました!
アバター
こんにちは、リッテルラボラトリーの清田です。 来たる9月7日(水)〜9日(金)に 富山大学 で開催される 第15回情報科学技術フォーラム(FIT 2016) のイベント企画にて、リッテルラボラトリーの石田・清田が登壇することになりました。 あわせて、ネクストとしてブース出展も行います。 多くの方々のお越しをお待ちしております! イベント企画「ここから始める情報処理 ~画像、音声、テキスト、検索、学習、一気にまとめてチュートリアル~」 (9/7 13:00-15:00) このセッションでは、音声認識ツールキット Kaldi 、自然言語処理の基本的ツール群、 検索性能評価ツールキット NTCIREVAL 、 Support Vector Machine など、さまざまな研究分野のツールのチュートリアルがまとめて行われます。 ネクストからは、昨年に多方面で話題になった ディープラーニングでおそ松さんの六つ子は見分けられるのか を題材として、 Chainer による画像識別のチュートリアルを石田が行います。 bohemia.hatenablog.com イベント企画「Real Estate Tech:不動産×IT ~ITが拓く不動産の未来~」 (9/8 9:30-12:00) 最近、金融分野の Fintech と同様に、不動産分野でも Real Estate Tech(ReTech) というキーワードが使われるようになってきました。今回のFITでは、不動産分野で情報活用を進めている企業や、不動産にかかわる研究を進めている研究者が一堂に会したパネルセッションが企画されています。 ネクストからは、昨年11月より研究者向けに提供を開始した HOME'Sデータセット の活用状況や、不動産分野特有の研究課題について清田がお話しします。 nextdeveloper.hatenablog.com また、現在リッテルラボラトリーとコラボレーションを進めている 100ninmap project の中心メンバーのお一人である和歌山大学の 宮部真衣先生 からも、住まい選び支援を目的とした街の雰囲気の可視化の取り組みについてお話しいただく予定です。 www.100ninmap.com
アバター
こんにちは。技術基盤部の磯野です。 先日に引き続きZipkinです。 今回は PHP + Symfony で動いている Webアプリケーションへのトレーサーの導入です。 前回の記事 → Zipkinを導入してみた(サーバー編) 構成 処理の流れ 処理の流れを追跡するためのリクエストヘッダ fluentdの設定 PHP(Symfony)側の実装 クライアントライブラリ Hoopak Apache Thrift ソースコード DI用設定ファイル(抜粋) イベントリスナクラス サービスコンテナクラス(イベントリスナにDIする用) 足りない機能を補充するためのラッパークラス WebAPI呼び出しのロギング追加 出力 構成 PHPは非同期に処理ができないので直接Zipkinサーバーにに投げるのではなくローカルのfluentdを利用してできるだけ短時間で処理が終わるようにしています。 画像のアプリケーション・フレームワーク → Zipkin Symfony2 Fluentd Sinatra 処理の流れ トレースデータの初期化(trace_id, span_idにユニークな値を設定する) Symfonyのイベントリスナのkernel.requestとkernel.responseをSubscribe kernel.requestイベントの通知時にリクエストの受付時刻(microtime)やURLなどを保存 WebAPI呼び出し時に処理の流れを追跡するための情報をリクエストヘッダに付与 WebAPI呼び出し処理の直前に送信時刻(microtime)やリクエスト先を保存 WebAPI呼び出し終了時に受信時刻(microtime)を保存し、API呼び出し開始時に保存した内容と一緒にローカルのfluentdにscribeで送信 kernel.responseイベントの通知時にレスポンス送信時刻(microtime)を保存し、kernel.requestで保存した内容と一緒にローカルのfluentdにscribeで送信 fluentdは順次Zipkinサーバーに転送 WebAPIが管理外のサービスの場合にはトレースデータの追跡情報をリクエストヘッダに付与せずに処理を行います。 なお、アプリケーションとWebAPIの呼び出しのトレースデータを別々にfluentdに流すようになっていますが、後述のライブラリの仕様です。 トレースするシステムが多い場合はまとめて送信するように改修した方がよさそうです。 処理の流れを追跡するためのリクエストヘッダ WebAPIの呼び出しのトレースデータは取得できますが、WebAPIからさらに別のWebAPIを呼ぶ場合には、一連の流れを認識するデータを持ちまわる必要があります。 そこで、HTTPヘッダにその流れを認識するために必要なデータを付与しています。 以下はそのHTTPヘッダとその説明です。 HTTP Header Type 説明 X-B3-TraceId 64 encoded bits *1 リクエストごとに共通のID、これで追跡情報を紐付ける X-B3-SpanId 64 encoded bits *1 計測ごとに一意に決まるID X-B3-ParentSpanId 64 encoded bits *1 直前のSpanId X-B3-Sampled Boolean (either “1” or “0”) *2 サンプリング対象かどうか X-B3-Flags a Long - *1 内部データは数値ですが、ヘッダに付与する際は16進数表現した文字列に変換します。 *2 rubygemsにあるzipkin-tracerが「X-B3-Sampled」を受け取る際に'true'(文字列)を要求するので文字列に変換します。 詳しくは以下URLの「HTTP Tracing」を参照してください。 http://zipkin.io/pages/instrumenting.html fluentdの設定 scribeで受け取りzipkinのscribe用のポートに転送するためのfluentdの設定はこんな感じです。 ※ 事前に fluent-plugin-scribe を導入しています。 <source> type scribe port 1463 </source> <match zipkin .**> type scribe host zipkinserver port 9410 field_ref message </match> PHP(Symfony)側の実装 続いてPHP(Symfony)側の実装です。 クライアントライブラリ まずはZipkinにトレースデータを送信するためのライブラリの導入をします。 Hoopak PHP用のライブラリは 公式 には存在しなかったので。GitHubで探しました。 1つしか見つからなかったのでこちらを利用しています。 https://github.com/Jimdo/hoopak This implementation might be incomplete and very naive とのことでちょっとドキドキですが、期待通りに動かなければ直せばいいだけなのでそのまま使います。 Apache Thrift HoopakはApache Thriftに依存しています。 https://thrift.apache.org/ 上記URLのページからダウンロードしてきたファイルを展開すると各言語用のライブラリが入っているのでPHP用を利用します。 ソースコード Symfonyをあまり理解せずに作っているので、使い方とか用語とか説明とか違ったらご指摘ください。 また、以下の3ファイルのrequireが必要なようなので事前にどこかでrequireしておいた方がいいです。 hoopak/gen-php/Scribe/Types.php hoopak/gen-php/Scribe/scribe.php hoopak/gen-php/Zipkin/Types.php DI用設定ファイル(抜粋) ExampleApp/Resources/config/services.yml parameters : zipkintracer.samplerate : 0.1 zipkintracer.service_name : webserver services : zipkin_tracer : scope : request class : ExampleApp\TracerService arguments : - @request - %zipkintracer.service_name% - %zipkintracer.samplerate% zipkin_event_listener : scope : request class : ExampleApp\TraceEventListener tags : - { name : kernel.event_subscriber } arguments : - @zipkin_tracer - @kernel - @request イベントリスナクラス <?php namespace ExampleApp; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; /** * Zipkinでのトレース用のイベントリスナ * リクエスト開始〜レスポンス直前の時間の計測を登録する。 **/ class TraceEventListener implements EventSubscriberInterface { /** * コンストラクタ * * @param ExampleApp\TraceService $trace * @param AppKernel $kernel * @param Request $request */ public function __construct ( $ tracer , $ kernel , $ request ) { $ this -> tracer = $ tracer ; $ this -> kernel = $ kernel ; $ this -> request = $ request ; } public static function getSubscribedEvents () { return array ( ' kernel.request ' => ' onKernelRequest ', ' kernel.response ' => ' onKernelResponse ', ) ; } public function onKernelRequest ( GetResponseEvent $ event ) { $ trace = $ this -> tracer -> getTrace () ; $ trace -> record ( \Hoopak\Annotation :: serverReceive ()) ; $ trace -> record ( \Hoopak\Annotation :: string ( ' server.env ', $ this -> kernel -> getEnvironment ())) ; $ trace -> record ( \Hoopak\Annotation :: string ( ' http.uri ', $ this -> request -> server -> get ( ' SCRIPT_URL ' ))) ; $ trace -> record ( \Hoopak\Annotation :: string ( ' http.query ', json_encode ( $ this -> request -> query -> all ()))) ; } public function onKernelResponse ( FilterResponseEvent $ event ) { $ trace = $ this -> tracer -> getTrace () ; $ trace -> record ( \Hoopak\Annotation :: serverSend ()) ; } } サービスコンテナクラス(イベントリスナにDIする用) <?php namespace ExampleApp; require_once ' hoopak/gen-php/Scribe/Types.php '; require_once ' hoopak/gen-php/Scribe/scribe.php '; require_once ' hoopak/gen-php/Zipkin/Types.php '; /** * Zipkinによるトレース用クラスの初期化処理&保持する * **/ class TracerService { private $ _tracer ; /** * コンストラクタ * * @param Request $request * @param float $samplerate Zipkinによるトレースをサンプリングするレートの指定 */ public function __construct ( $ request , $ service_name , $ samplerate = 1.0 ) { $ method = strtolower ( $ request -> server -> get ( ' REQUEST_METHOD ', ' GET ' )) ; $ tracer = new \Hoopak\ZipkinTracer ( new \Hoopak\ScribeClient ( ' localhost ', 1463 )) ; $ this -> _trace = new TraceWrapper ( $ method , null , null , null , $ samplerate , array ( $ tracer )) ; $ ipaddress = $ request -> server -> get ( ' SERVER_ADDR ' ) ; $ port = $ request -> server -> get ( ' SERVER_PORT ' ) ; $ this -> _trace -> setEndpoint ( new \Hoopak\Endpoint ( $ ipaddress , $ port , $ service_name )) ; } public function getTrace () { return $ this -> _trace; } } 足りない機能を補充するためのラッパークラス あとで整理してhoopak側に取り込んでプルリク出したいと思います。 <?php namespace ExampleApp; /** * Hoopak\TraceのWrapクラス * **/ class TraceWrapper { /** * @var Hoopak\Trace **/ private $ _trace ; /** * @var boolean * Hoopak\Traceエラー時に次回以降処理を転送しないためのフラグ * **/ private $ _error = false ; /** * @var array * \Hoopak\ScribeClientなどのインスタンスを持つ配列 **/ private $ _tracer = array () ; /** * @var \Hoopak\Endpoint **/ private $ _endpoint = null ; /** * トレースデータを取得するかどうか **/ public $ sampled = true ; /** * @var array APIサーバーに送信するZipkinヘッダの対応表 **/ private $ _headers = array ( ' traceId ' => ' X-B3-TraceId ', ' parentSpanId ' => ' X-B3-ParentSpanId ', ' spanId ' => ' X-B3-SpanId ', ' sampled ' => ' X-B3-Sampled ', #'flags' => 'X-B3-Flags' ) ; /** * コンストラクタ * * @param Hoopak\Trace */ public function __construct ( $ method , $ traceId = null , $ spanId = null , $ parentSpanId = null , $ samplerate = 1.0 , $ tracers = array ()) { if ( !$ traceId ) { $ traceId = $ this -> _id () ; } if ( !$ spanId ) { $ spanId = $ this -> _id () ; } $ this -> _tracers = $ tracers ; $ this -> _trace = new \Hoopak\Trace ( $ method , $ traceId , $ spanId , $ parentSpanId , $ tracers ) ; if ( $ samplerate < 1.0 ) { $ this -> sampled = ( $ samplerate == 0 ) ? false : ( $ samplerate > ( mt_rand () / mt_getrandmax ())) ; } } /** * @see \Hoopak\Trace::record() * sampled=falseの時は何もしない **/ public function record ( $ annotation ) { if ( !$ this -> sampled ) { return ; } $ this -> __call ( ' record ', array ( $ annotation )) ; } /** * @see \Hoopak\Trace::child() * \Hoopak\Trace::_id()が同一IDを返却する確率が高すぎるので、使わないように処理を上書き **/ public function child ( $ name ) { $ samplerate = $ this -> sampled ? 1.0 : 0.0 ; $ trace = new self ( $ name , $ this -> traceId, $ this -> _id () , $ this -> spanId, $ samplerate , $ this -> _tracers ) ; $ trace -> setEndpoint ( $ this -> _endpoint ) ; return $ trace ; } /** * @see \Hoopak\Trace::setEndpoint() * このクラスでもendpointを変数として保持する **/ public function setEndpoint ( $ endpoint ) { $ this -> _endpoint = $ endpoint ; $ this -> __call ( ' setEndpoint ', array ( $ endpoint )) ; } /** * Hoopak\Traceに処理を移譲するためのメソッド * 移譲先でエラーが発生した場合は、握りつぶす * * 個別のメソッドに関しては移譲先を参照 * @see hoopak/src/Hoopak/Trace.php * **/ public function __call ( $ name , $ arguments ) { if ( $ this -> _error ) { return ; } try { return call_user_func_array ( array ( $ this -> _trace, $ name ) , $ arguments ) ; } catch ( \ Exception $ e ) { $ message = " exception ' " . get_class ( $ e ) . " ' with message ' " . $ e -> getMessage () . " ' in " . $ e -> getFile () . " : " . $ e -> getLine () ; error_log ( $ message ) ; $ this -> _error = true ; } } /** * \Hoopak\Traceのパブリックなインスタンス変数を取得するためのメソッド * * 個別の変数に関しては以上先を参照 * @see hoopak/src/Hoopak/Trace.php **/ public function __get ( $ name ) { return $ this -> _trace ->$ name ; } /** * Zend\Http\Clientでのリクエストデータ、レスポンスデータを元にZipkinへのトレース登録とを行う。 * また、リクエストヘッダにZipkinのトレース情報転送用のヘッダを付与する。 * * @param string $name リクエスト送信先のサービス名称 * @param Zend\Http\Client $client * @param callable $block ( * @param ExampleApp\TracerWrapper * @return Zend\Http\Response * ) * @return Zend\Http\Response * **/ public function traceWithHTTPClient ( $ name , $ client , $ block ) { $ tracer = $ this -> _createChildHTTPTracer ( $ name , $ client ) ; $ tracer -> _prepareHTTPClient ( $ client ) ; $ tracer -> record ( \Hoopak\Annotation :: clientSend ()) ; $ httpResponse = $ block ( $ tracer ) ; $ tracer -> record ( \Hoopak\Annotation :: string ( ' http.status ', $ httpResponse -> getStatusCode ())) ; $ tracer -> record ( \Hoopak\Annotation :: clientReceive ()) ; return $ httpResponse ; } /** * Zend\Http\Clientのデータを元に子トレースインスタンスを作成し返却する。 * * @param string $name リクエスト先サービス名 * @param @param Zend\Http\Client $client * @return ExampleApp\TracerWrapper * **/ private function _createChildHTTPTracer ( $ name , $ client ) { $ uri = $ client -> getUri () ; $ query = $ client -> getRequest () -> getQuery () ; $ method = $ client -> getRequest () -> getMethod () ; $ trace = $ this -> child ( strtolower ( $ method )) ; $ serverAddress = \Hoopak\Annotation :: string ( ' sa ', ' 1 ' ) ; $ serverAddress -> endpoint = new \Hoopak\Endpoint ( $ uri -> getHost () , $ uri -> getPort () , $ name ) ; $ trace -> record ( $ serverAddress ) ; $ trace -> record ( \Hoopak\Annotation :: string ( ' http.uri ', $ uri -> getPath ())) ; $ trace -> record ( \Hoopak\Annotation :: string ( ' http.query ', json_encode ( $ query ))) ; return $ trace ; } /** * Zend\Http\Clientにトレースデータ転送に必要なリクエストヘッダを付与する * @param Zend\Http\Client $client * **/ private function _prepareHTTPClient ( \Zend\Http\Client $ client ) { foreach ( $ this -> _headers as $ key => $ value ) { $ headers [ $ value ] = $ this -> _getStringData ( $ key ) ; } $ client -> setHeaders ( $ headers ) ; } /** * * @param $key string key of data * @return string- **/ private function _getStringData ( $ key ) { $ value = $ this ->$ key ; switch ( gettype ( $ value )) { case ' integer ' : $ ret = sprintf ( " %016s ", dechex ( $ value )) ; break ; case ' boolean ' : $ ret = $ value ? ' true ' : ' false '; break ; default: $ ret = ( string ) $ value ; break ; } return $ ret ; } private function _id () { return ( int ) round ( microtime ( true ) * 1000 * 1000 ) ; } } WebAPI呼び出しのロギング追加 このようにWebAPIを呼び出している部分(Zend\Http\Client)があったら $response = $client- > send(); こんな感じに書き換える事でWebAPIへのリクエストのトレースが有効になります。 $tracer = $this- > container- > get('zipkin_tracer')- > getTracer(); $response = $tracer- > traceWithHTTPClient("webapi", $client, function($childTracer) use ($client) { return $client- > send(); }); 出力 以下の赤で囲った部分が今回の作業により記録されるようになります。 次回は、WebAPIサーバーへの導入(Ruby編)の予定です。
アバター
こんにちは、リッテルラボラトリーの清田です。 このたび、 電気通信大学 に新設される 人工知能先端研究センター (AIX)に、 サポーター企業としてネクストが参画 することになりました。 リッテルラボラトリーでは、電気通信大の 栗原研究室 と、ソーシャルメディアを通じて住まい探しユーザーを理解することを目指した共同研究を推進してきました。その成果は、 人工知能学会全国大会 (JSAI 2015) や、2015年12月にシンガポールで開催された国際ワークショップ DOCMAS/WEIN 2015 などで発表しております。 nextdeveloper.hatenablog.com JSAI2015 ツイートタイムラインへの階層的クラウドソーシングの適用による住まい探しユーザの背景ニーズ理解 from Yoji Kiyota www.slideshare.net Mining User Experience through Crowdsourcing: A Property Search Behavior Corpus Derived from Microblogging Timelines from Yoji Kiyota www.slideshare.net 今後、共同研究を通じて一人ひとりの生活に密着した住まいなどの領域でのユーザー理解をさらに深めていくとともに、 HOME'Sデータセット の提供を通じて活用されつつある不動産物件画像へのdeep learning適用で得られた知見なども活かし、人工知能技術を身近にしていくためにAIXの活動に積極的に協力していきます。 今後の進展にご期待ください!
アバター
こんにちは。技術基盤部の磯野です。 弊社ではここ数年、HOME'Sのクラウド化やマイクロサービス化を推進しています。 アプリケーションのクラウドサービスへの移行に関してはそろそろ終わりが見えてきているのですが、 マイクロサービスに関してはまだまだ道半ばということもあり、推進していくにあたって、 各サービス間の依存関係やトレース情報を可視化する手段としてzipkinをAWS上に試験的に導入してみました。 今回はZipkinサーバーの導入までの手順についてまとめたいと思います。 Zipkin とは データストレージの選択 InMemory MySQL いいところ 残念なところ Cassandra いいところ 残念なところ Elasticsearch いいところ 残念なところ 基本構成 サービスのインストール MySQLの設定 zipkinのインストールと確認用の起動 supervisordのインストール おまけ zipkinのすぐに使いそうな環境変数 Zipkin とは 分散環境における各サービスの呼び出し状況を収集・可視化できるシステムです。 文字だけだとよくわかりませんが、サービス間の呼び出しをこんな感じで可視化できるサービスです。 ※個人環境のデータです。 データストレージの選択 Zipkinは標準で4つのデータストレージに対応しています。(InMemory, MySQL, Cassandra, Elasticsearch) 今回は試験的な導入ということもあり、運用面や金銭面も加味して、とりあえずMySQL(RDS-Aurora)で進めています。 以下に各項目について軽くまとめました。最終的にはElasticsearchもしくはCassandraに切り替えたいと考えています。 InMemory 永続化されないので確認的な利用以外では利用しにくい MySQL いいところ わかりやすい RDSを利用すればほとんど管理コストがかからない 残念なところ パフォーマンスに問題がある 書き込みは問題なかったが、読み込みは顕著に影響が出た サンプリングレートをかなり下げているにもかかわらず、1日〜2日程度(数百万レコード)経過しただけで目に見えて検索が遅くなる * r3.largeを利用していることも急激な速度低下の原因の一つだと思われる Cassandra いいところ Expireを設定できるので明示的なデータ削除が必要ない 大量のデータでも高速に処理できる 残念なところ マネージドサービスがあるわけではないので自分でインスタンスの管理をする必要がある 社内でのCassandraの評判が悪すぎる。誰も運用したくないみたい Elasticsearch いいところ 大量のデータでも高速に処理できる 残念なところ Amazon Elasticsearch Serviceで利用できない Amazon Elasticsearch Serviceはノード一覧をマスクした状態で返却するので、デフォルトのアダプタでは利用できない様子 マネージドサービスが利用できないので自分でインスタンスの管理をする必要がある 基本構成 まずは基本構成として、以下のようにする予定です。 今回は右側の管理用VPC内の構成を作る作業を行います。 サービスのインストール MySQLの設定 MySQL5.6で利用できるので、今回はMySQL5.6互換なAuroraを利用します。 ※Auroraの起動方法やセキュリティグループの設定などについては割愛します。 まず、新規にパラメータグループを作り、innodb_file_formatをBarracudaに設定を行います。 作成したパラメータグループを指定してAuroraインスタンスを起動します。 データベース名は標準でzipkinにしておくとZipkinサーバー起動時に指定しなくて済みます。 またzipkinに必要なテーブルを作ります。github上にsqlファイルがあるので、そちらを取得してsqlを流します。 {}で囲ってある部分は環境依存なので、必要に応じて変更してください。 $ sudo curl ' https://raw.githubusercontent.com/openzipkin/zipkin/master/zipkin-storage/mysql/src/main/resources/mysql.sql ' -o /tmp/mysql.sql $ mysql -h{ zipkin_aurora_host } -u{ zipkin_aurora_user } -p -Dzipkin < /tmp/mysql.sql 以下のファイルに注意事項が書いてあるので詳しくはこちらを参照してください。 https://github.com/openzipkin/zipkin/blob/master/zipkin-storage/mysql/README.md zipkinのインストールと確認用の起動 EC2インスタンスを起動します。 セキュリティグループを設定する場合にはインバウンドで9410(scribe),9411(http)の2つのポートを解放しておく必要があります。 mysqlの設定時と同様{}で囲ってある部分は環境依存なので、必要に応じて変更してください。 $ sudo yum install mysql java-1.8.0-openjdk java-1.8.0-openjdk-devel $ sudo alternatives --set java /usr/lib/jvm/jre-1.8.0-openjdk.x86_64/bin/java $ sudo mkdir /opt/zipkin $ sudo curl -L ' https://search.maven.org/remote_content?g=io.zipkin.java&a=zipkin-server&v=LATEST&c=exec ' -o /opt/zipkin/zipkin.jar $ sudo STORAGE_TYPE = " mysql " MYSQL_HOST = " {zipkin_aurora_host} " MYSQL_USER = " {zipkin_aurora_user} " MYSQL_PASS = " {********} " java -jar /opt/zipkin/zipkin.jar ブラウザから http://zipkinserver:9411/ を開くことでトップページにアクセスできます。 また、 http://zipkinserver:9411/mappings にはURLのマッピング設定があります。 その中でも http://zipkinserver:9411/env は設定(環境変数、デフォルト値など)を返却してくれるので重宝します。 ただし、環境変数として渡したパスワードをマスクせずに返却するようなのでパスワードを利用する場合はアクセス制限した方がよさそうです。 supervisordのインストール daemon化するためにsupervisordを入れてupstartの設定を追加しました。 ※ pipをupgradeするとなぜか/usr/bin/pip → /usr/local/bin/pipになってしまうのでちょっと困ってます。 $ sudo pip install pip --upgrade $ sudo /usr/ local /bin/pip install supervisor $ cat <<EOF | sudo tee /etc/init/supervisord.conf description "supervisord" start on runlevel [2345] stop on runlevel [!2345] respawn exec /usr/local/bin/supervisord -n EOF $ mkdir /var/log/supervisor $ mkdir /etc/supervisor.d $ /usr/ local /bin/echo_supervisord_conf | sudo tee /etc/supervisord.conf $ cat <<EOF | sudo tee -a /etc/supervisord.conf [include] files = /etc/supervisor.d/*.ini EOF $ cat <<EOF | sudo tee /etc/supervisor.d/zipkin.ini [program:zipkin] command=java -jar zipkin.jar directory=/opt/zipkin autostart=true autorestart=true stopasgroup=true logfile=/var/log/supervisor/zipkin.log environment=STORAGE_TYPE="mysql",MYSQL_HOST="{zipkin_aurora_host}",MYSQL_USER="{zipkin_aurora_user}",MYSQL_PASS="{********}",SELF_TRACING_ENABLED="false" EOF $ sudo initctl start supervisord これで万が一落ちても、supervisordが起動してくれます。 以上で基本的な設定は終了です。 おまけ zipkinのすぐに使いそうな環境変数 環境変数 デフォルト値 説明 SELF_TRACING_ENABLED true falseにすることでzipkin自身のトレースを停止できる COLLECTOR_SAMPLE_RATE 1.0 サンプリングレート 0.0〜1.0の範囲を指定。0にすればロギングを停止できる COLLECTOR_PORT 9410 scribe用ポート STORAGE_TYPE mem mem,cassandra,elasticsearch,mysqlから選択可能 MYSQL_HOST localhost 接続先MySQLホスト名 MYSQL_TCP_PORT 3306 接続先MySQLポート MYSQL_USER - 接続先MySQLユーザー名 MYSQL_PASS - 接続先MySQLパスワード MYSQL_DB zipkin 接続先MySQLデータベース QUERY_PORT 9411 Webサーバーポート すべての環境変数はこちらを参照してください。 https://github.com/openzipkin/zipkin/blob/master/zipkin-server/src/main/resources/zipkin-server.yml 次回は、アプリケーションサーバーへの導入(PHP編)の予定です。
アバター
Apple原理主義者の大坪です。人は思いがけない出来事に直面すると、その理由を探さずにはいられない。お財布を落としてしまった!なぜだろう?きっと今朝黒猫印をつけた車が私の前を横切ったのがいけなかったのだ、とかなんとか。 いきなり何を書いているかといえばあれですよ。年に一度行われるAppleの開発者向け会議WWDCのチケットが当たったんですよ。いや、大丈夫。ちゃんと理解してます。これは奇跡でもなんでもなくarc4random_uniform関数 *1 がたまたま「参加」の値を返しただけ、と。しかしこれは私の常軌を逸したAppleへの愛がなせる技ではなかろうか、と頭の片隅で考えているのも事実。 などと のんきなことを言っている場合ではありません。わーいわーいと喜んでいいのは30秒ほど。早く正気に帰りあれこれの手配をしなくてはなりません。 まずはホテルと航空券の手配。毎年驚かされるのはSan Fransiscoエリアでの宿泊代の高騰ぶり。おまけに少しでも宿泊場所確保に出遅れるとあっというまに満室の嵐になる。 「予算内の場所はないか」と血眼になってあちこちのサイトを探し「あったー」と思ったら予約ボタンを押す前に こちらの情報 などを確認しましょう。安くてしかも空室があるホテルがこうしたエリアに存在している確率は悲しくなるほど高い。 そうした壁を乗り越え、宿と足を確保すると、今度は情報収集を始める。去年は現地で前夜に、今年は日本で一週間前に参加者同士の飲み会が行われました。主催者の方には感謝の他ありません。そこで必ず話題になるのが   「初日のキーノート何時から並ぶ?」   2013年に参加した時は、迂闊にも寝過ごしてしまい並び始めたのは7時過ぎ。それでも特に不満のない場所に座れた。話のネタ的に真夜中から並ぶという選択肢もありますが、そんなに無理しなくていいのではないか。そもそも列のものすごく前に並べたところでどうせ会場内最前列のエリアは全て「予約済み」だから座れないし。あまり遅く行くと"Overflow Room"なるビデオ中継でしかキーノートを見られない部屋に回されるらしいけど、それさえ回避できれば。   しかし   そこに立ちはだかるのが時差ボケ。長旅で疲れよれよれとベッドにはいったはずなのに、真夜中にパッチリ目が覚める。まだ数時間は眠れると毛布をかぶっても目は冴える一方。諦めてMacBookなど叩いていると 「並ばなくていいのか」 という強迫観念が迫ってくる。San Fransiscoくんだりまで来て、2chなんか見ている場合か。いや、まだ夜明けまでは時間がある。とはいって眠くはないし、やることもない。そうしているうち「ええい、行ってしまえ」とホテルを飛び出す。そして氷のような寒さ *2 の中長い長い行列に立ち尽くし、己の判断の愚かさに呪いの言葉を吐く。 これは去年の写真。ちなみに時間は午前4時半     というのが去年私に起こったこと。今年はもうそんなことはしないもんね、と固く決意するわけでした。これにはもう一つ理由があり、今年は初日の場所が例年とは変わっています。去年まではイベント全日Moscone Westで行われたのですが、今年は初日のみBill Graham Civic Auditorium。いいニュースはおそらく収容人数がMoscone Westより多いこと。悪いニュースは辺りの治安があまりよろしくないこと。以前別の出張で来た時、明るい時間帯なのにいろいろな人が周りにたむろしていたことを思い出す。あそこに暗いうちから数時間立っているのが良い選択肢だろうか?いや違う。というわけでWWDC(及び周辺イベント)に参加する人たちの間でも「明るくなってから移動が良いよね」ということで意見が一致する。 そのようにちゃんとあれこれ考えていたので 「あーよく寝た」とパッチリ目が覚め、ふと見た枕元の時計がこんな表示をしていても驚かない。ここでやるべきことは静かに目を閉じ布団をかぶって心から雑念を追い払うこと。 今日のKeynoteではどんな発表があるか?とか考えてはいけない。 どんなサプライズがあるだろうか?とか考えてはいけない。 あまり可能性はないとはいえ、MacBookが発表されないだろうか?とか考えてはいけない。 使っているMacBookAirもう六年目。そろそろ買い換えないと、とか考えてはいけない。 .... 目覚ましの音で飛び起きれば午前6時。なんとすばらしい。時差ぼけに打ち勝ち眠れたではないか、 と勝利の喜びにひたりながらFacebookを見る。するともう並んでいる人がいるのに気がつく。そうか。並んでいる場所はセキュリティがちゃんとしているのか、、、とか考えながらふと気がつけば猛然と出かける支度をしている。ちょっとまて。俺は昨日ホテルを7時に出ると決めたのだ、と自分に言い聞かせているうち準備万端になってしまう。いいや、もう出ちゃおう。 WWDC参加者にはRegistration時ジャケットが配られます。ここ数年ジャケットのデザインにはパターンがあり、黒一色で背中にその年の下二桁が書かれている。朝の街を会場に向かって歩いて行くと、背中に「16」と書かれたジャケットを着た人をちらほら見かける。会場が近づくにつれ、目に入る「16」の数が増えていく。 こんだけ参加者がいれば、きっと怪しい人に絡まれる危険性は少ないだろう、と根拠のないことを考えながら歩き続ける。そのうち会場が見えてきました。 列に並ぶ時点でSecurityの人にバッジを見せます。列の近くにはあまーいマフィンの類とコーヒーも用意されている。ぱくぱく食べたいところですが、調子にのって飲みすぎトイレに行きたくなっても困る。ぐっとこらえて少しだけとります。 それから会場に入ることができた午前9時まで延々この光景を目にすることになる。しかしそうした時間にも見るべきもの、考えるべきことは存在している。私にとっては寒いとしか思えない状況。しかしなぜ前に立っているお兄さんはTシャツ短パンでへらへら笑っているのだ。周りからは様々な言葉が聞こえます。日本語、英語、中国語、フランス語、ドイツ語、スペイン語、そして私が知らない言葉。皆これから始まるキーノート、そしてWWDCを心から楽しみにしている。 そんなことを考えんながらぼんやり建物を見る。そしてあることに気がつく。上の写真をみて「?」と思いませんか?その理由がわかったのはキーノートを聞き、そしてこの日の夕方にある光景を目にしてから。     7月1日に弊社でWWDC2016共有会を開催いたします。 connpass.com ゲストスピーカーの岸川さんも含めライトニングトークでどんなお話が聞けるのか。懇親会で皆さんとどんなお話ができるのか今からワクワクしております。私も登壇させていただきますので、皆さんの貴重な時間を無駄にしないよう、今から頭を悩ませております。 もしご興味をお持ちでしたら、ぜひご登録ください。 *1 : iOSで乱数を返してくれる関数です。 *2 : ”私が経験したもっとも寒い冬はサンフランシスコの夏だった。” といはマーク・トゥエインの言葉
アバター
こんにちは。おうちハッカー@リッテルラボラトリーの石田です。 2016年6月6日~9日に開催された第30回人工知能学会全国大会に行ってきました。私は画像系及び深層学習に興味があるので、特に画像系と深層学習系セッションを見て回りました。 そこで主に自分が見たセッションを元に、今年の人工知能学会の画像に関わる深層学習の発表をまとめてみました。 私が見た・読んだ範囲で、「 各分野にCNNを適用した研究 」「 画像系深層学習の理論的な研究 」「 画像ではないが気になった深層学習の研究 」に分けて紹介します。 自分で実際に見た発表については、おすすめ度をつけています。個人の主観によるものですので、弊社の見解とは関係がありません。 ではどうぞ。 各分野にCNNを適用した研究 ここでは、画像系で大きな成果を上げているCNN(畳み込みニューラルネットワーク)を、各分野の画像解析に適用してみた研究を紹介します。 画像特徴量を利用したユーザプロファイルの拡張とローカルショップ推薦への応用 https://kaigi.org/jsai/webprogram/2016/pdf/156.pdf おすすめ度:★☆☆ 基本はSIFT特徴量をBoVWに変換して、ユーザーの訪問場所の画像から、特徴量の近しいレストラン等を推薦する研究。論文中では述べられてませんが、発表ではCNNを用いて、ランチ、ディナー、ナイトライフなどを分類して利用していました。 深層学習を用いたファッションコーディネート因子の抽出 https://kaigi.org/jsai/webprogram/2016/pdf/101.pdf おすすめ度:★★☆ 服の種類を判定、ユーザーへの推薦を目的とする研究。 従来はトップス、スカートなどのの上位カテゴリと、カーディガン、ニットなどのサブカテゴリを同時にCNNで推定していましたが、提案手法のLayered CNNではトップカテゴリの判定器→サブカテゴリの判定器の順に2層構造の判定器で構成されており、従来より精度が向上したとのことです。 その他の知見としては、模様などのスペクトラムは、別の特徴量を使った方法が有効なこと、画像の前処理が重要なことが述べられていました。 Deep Learning技術をベースとした異常画像検出 https://kaigi.org/jsai/webprogram/2016/pdf/664.pdf おすすめ度:★★★ SUUMOの戸建の物件画像について、2種類の異常検知を行った研究。人が写り込んでいるような画像を省くため、物体検知と分類を同時に行う手法であるFaster R-CNNで人を検出していました。もう一つは、CNNの中間層の特徴量をX-meansでクラスタリングして、建築中や土地のみの異常画像のクラスタの生成に成功しています。 同業の不動産情報サイト関連研究として、興味深く聞かせてもらいました。 地球観測衛星画像上の地物自動認識 https://kaigi.org/jsai/webprogram/2016/pdf/1019.pdf おすすめ度:★★☆ LANDSAT衛星写真からCNNでソーラーパネル設置領域を判別する研究。教師データが少ないが、RGBに加え赤外線などのバンドを入力に入れることで、精度向上に大いに寄与していることを示していました。パラメータ調整にはガウス過程を用いたベイズ最適化を用いているそうです。 ディープラーニングを適用した衛星画像からの土地被覆分類手法の評価 https://kaigi.org/jsai/webprogram/2016/pdf/881.pdf おすすめ度:★★☆ 前の研究と同じく衛星画像を用いて、都市、森、水源などに分類する研究。 ベイス推定を利用した自動パラメータ調整を利用。精度は7割程度。既にある分類基準を元に、CNNのモデルのラベルをどう定義するかが精度に大きく影響するようでした。 深層学習を用いた SNS プロフィール画像から䛾投稿者属性推定 https://kaigi.org/jsai/webprogram/2016/pdf/778.pdf おすすめ度:見てません CNNでFacebookのプロフィール画像から、性別、年齢、性格を推定する研究。顔画像をHaar-like検出器+adaBoostによる顔領域検出で切り抜いた画像の精度が向上しているようです。 実環境におけるロボットの物体認識 https://kaigi.org/jsai/webprogram/2016/pdf/363.pdf おすすめ度:★☆☆ Pepperなどのロボットのためのリアルタイム周辺環境認識のために、BINGで物体候補領域を検出、CNNのCaffeのリファレンスモデルで物体種別を分類する研究。Intel RealSenseのデプスカメラを利用して、検出したものの距離を計測できるようにしていました。 現状ではGPUにTitan X使用で、処理に一枚あたり1秒かかるそうです。 畳み込みニューラルネットワークを用いた微小眼球運動の検出 https://kaigi.org/jsai/webprogram/2016/pdf/988.pdf おすすめ度:★★☆ 人の注意状態を表す眼球のマイクロサッカード(MSC)をロバストに検出するために、眼球の位置を入力としてFaster R-CNNを参考した手法を使った研究。特徴抽出部と識別部の2段構成で、特徴抽出部は2層畳み込みで特徴波形を抽出、識別部はConvMLPを結合したモデルを利用してMSCの確率を推定しています。 Convolutional Neural Networkによる写真と手描きスケッチの認識 https://kaigi.org/jsai/webprogram/2016/pdf/1056.pdf おすすめ度:★★☆ 手書きスケッチを描いて類似画像を検索するためにCNN学習させたいが、大量のデータセットの作成が困難なため、画像やイラストを加工した画像を用い学習を行わせる研究。画像とスケッチが混ざったテストデータでも高精度に20種類の動物を分類できています。 畳み込みニューラルネットワークを用いた表情表現の獲得 https://kaigi.org/jsai/webprogram/2016/pdf/873.pdf おすすめ度:★☆☆ 顔の表情データセットをCNNで分類する研究。表情の専門知識を用いて特徴量を設計して作られた既存研究に近い精度が出ています。 画像系深層学習の理論的な研究 畳込みニューラルネットワークのための新しい半教師あり学習法 https://kaigi.org/jsai/webprogram/2016/pdf/893.pdf おすすめ度:★★★ CNNには大量の正解ラベル付きの正解データが必要だが、最初にラベルなしの画像データで教師なし学習をし、その後教師あり学習に切り替えるという半教師あり学習を行うと、学習速度が向上するという研究。 教師なし学習時は、教師ありの10倍ほどの画像を用意し、正解を最もスコアの高かったユニットのラベルとし、正解を確度の低いものとして扱って学習させています。 逆畳み込みニューラルネットワークを用いた輪郭検出 https://kaigi.org/jsai/webprogram/2016/pdf/763.pdf おすすめ度:★★☆ 輪郭抽出を行うHEDという手法について、一部に逆畳み込みネットワークを使うことでよりきれいな輪郭抽出を試みる研究。 HEDはCNNの全結合層が存在しないFully Convolutional Network(FCN)を用い、プーリングで小さくした特徴量を画像サイズまで拡大するときに線形補完を使っていたが、代わりに逆畳み込みを導入してみたところ、従来手法より若干きれいな輪郭の抽出ができていました。 深層学習における敵対的ネットワークと注視を用いた画像生成の試み https://kaigi.org/jsai/webprogram/2016/pdf/811.pdf おすすめ度:★★☆ 深層学習による画像生成の現状の問題点として、大きな画像が生成できず、細部が曖昧になってしまう点があります。 そこで注視メカニズムを使い、部分画像を複数回に渡って学習・生成し、また敵対的ネットワークを導入し画素単位での誤差の修正を試みる研究。 MNISTという手書き文字データセットで実験を行っています。 【補足】敵対性ネットワークについては、昨年末話題になった、敵対性ネットワークによる画像生成の記事を見ると、敵対性ネットワークの概念について理解できると思います。 Chainerで顔イラストの自動生成 - Qiita 深層学習における敵対的ネットワークによるラベル推定と半教師あり学習 https://kaigi.org/jsai/webprogram/2016/pdf/829.pdf おすすめ度:★★★★ 半教師あり学習で高精度な分類機を作るため、敵対的自己符号化器を用いた研究。符号化器が獲得する潜在変数として、従来のzに加え、yを導入し、一方にコンテンツ識別に必要な情報、もう一方にその他のスタイル情報を敵対性ネットを用いて学習させることで、コンテンツとスタイルを分離することができ、精度向上を図っています。 スタイルとコンテンツが分離できたことで、それぞれを別に指定して画像生成が可能になりました。例えば、ポップ風の「3」の画像といった指定で生成できそうです。 つまりこの研究では、半教師あり学習の精度向上と、画像生成技術における生成画像のコントロールの2つをもたらしていると言えます。 画像以外の深層学習の研究 マルチエージェントによるDeep Learningの提案 https://kaigi.org/jsai/webprogram/2016/pdf/953.pdf おすすめ度:★★★ 現状の深層学習では、何層にするか、各層のユニットの数をいくつにするか決めて実験してうまくいったものを使っていますが、将来的に膨大な作業になりそうです。 そこで各ユニットをエージェントにしてしまい、各ユニットが局所的な情報のみを持って独立して行動することで、ネットワークを学習中に自動で変わっていく手法を提案している研究。SDAというデータの一部を隠して再構成させる手法がありますが、この手法とほぼ同等の性能を持つマルチエージェントによる深層学習を実現しています。 Deep Neural Network を用いた株式売買戦略の構築 https://kaigi.org/jsai/webprogram/2016/pdf/975.pdf おすすめ度:★★★ 既存研究では、株価の予測がされていますが、どのタイミングでどの量を売買するかまで議論されていません。そこで深層学習を用いて売買タイミング、取引量まで提案するシステムを構築する研究。 テクニカル指標であるトレンド系とオシレータ系のモデルをそれぞれ作成、過去の株価データをもとに学習させたところ、両モデルの複合型が高い成果を残しています。 また、その時のトレンドによって、トレンド系とオシレータ系のどちらが有効か異なるため、直近の精度により信頼度を設定、信頼度によって取引量を決めることで、さらに成果が向上しています。 深層行動認識モデルのユーザ特化圧縮 https://kaigi.org/jsai/webprogram/2016/pdf/593.pdf おすすめ度:★★★ IoTにおけるセンサベース行動認識において、学習済みモデルをユーザーに特化させることでモデルの圧縮を試みる研究。 センサ情報を生で送るのはプライバシー的に怖いので、解析済みのデータのみを送りたいところです。しかし大量に設置するセンサ側やスマホのメモリ容量は限られ、学習済みモデルをそのまま置き辛いです。 そこで蒸留という方法でそのユーザーにとって不要なユニットを削除することで、モデルの圧縮を行っています。教師モデルと生徒モデルを使った提案手法により、30%まで圧縮しても精度が落ちないことが示されています。 感想的なもの 人工知能学会への参加は2回目でしたが、去年に比べてディープラーニング関連の研究が激増していました。 特に各分野にCNNを適用した例が非常に多く、広い分野で良い成果を残していました。CNNを適用する際のテクニックも多く学べました。 また画像生成技術が昨年末に話題になったり、 画風変換アルゴリズム などが注目され、個人的に画像の生成に興味を持っていました。絵を全くかけない自分にとって、アルゴリズムで絵を作れるというのは、表現手段が増えてとても楽しいのもです。 私自身も、 DCGANで間取りを生成 させたり、 画風変換アルゴリズムでいろんな「だが断る」を作っ たりして遊んでいますが、画像が荒かったり、特徴抽出がうまくできなかったりして、まだまだな部分があります。 今回の人工知能学会でも、高精度な画像生成や特徴抽出の改善などの研究があり、どんどん改善されていくのが楽しみになりました。 理論的な研究も非常に興味深く、教師データ収集の手間を減らす、モデルを圧縮する、モデルの組み合わせの試行を無くすなど、現状の深層学習における問題点を本質的に解決する研究は凄いと思いました。 本当に深層学習周りの技術の進歩は速すぎて、驚くべき成果が多いので、これからも積極的に情報を収集していこうと思います。
アバター
こんにちは!iOSチームの塙です! 来週に迫った WWDC2016 ですが、どんなサプライズが待っているんでしょうかね! 私もAltConfなどの周辺イベントに参加しに行きます!(現地でお会いできたらご飯行きましょう!) Swift3.0 の話は確実にメインで出てくるでしょうね!しっかりと勉強しておきたいです。 特に ++ -- オペレータの廃止はCに慣れ親しんだ方々には衝撃だったはずです。詳しくは こちら 他には噂レベルですが、サードパーティのアプリで使用出来るSiriAPIの登場やiOS10、WatchOS3、新AppleMusic、iPhone7、新MacBookなどなど… こんなに熱い情報を自分のPCの中に留めておくのはもったいない! では共有しようではないか!と始まったWWDC共有会ですが、 今年も弊社、ネクストで行います! 現地に参加される方も、自宅でまったりKeynoteをストリーミングで見る方も、何もしない方も! 熱い情報は熱いうちに共有しましょう!以下概要です! 概要 日時 2016/07/01(金) 19:00 – 22:00頃 場所 株式会社ネクスト 東京都港区港南2-3-13 品川フロントビル3F エレベーターにて3Fまで登っていただきますと、左手に受付スペースがございます。 参加費 無料 です! 内容 弊社エンジニアからの現地報告 LT枠で申し込み頂いた方のLT 懇親会(軽食をご用意いたします) 定員 LT枠(先着): 7名 (10分前後のLTの準備をお願いいたします) オーディエンス枠(抽選): 100名 注意事項 Apple Developerアカウントを持っている方に限定させていただきます。 Appleとの契約上守秘義務の課せられている情報等については、個人の責任において管理をお願いします。 なお上記に伴いまして、入室時に誓約書への記載をお願いいたします。 Wifi、電源は準備しておりますが限りがあり、回線品質の保証は出来ませんのでよろしくお願いします。 詳細&参加申し込み connpass.com 皆様のご参加を心からお待ちしております!
アバター
こんにちは、リッテルラボラトリーの清田です。 2016年6月6日(月)〜6月9日(木)に福岡県北九州市で開かれる 2016年度人工知能学会全国大会 (JSAI 2016) に、株式会社ネクストとして協賛・ブース出展します。 今年は、人工知能 (Artificial Intelligence) という分野ができるきっかけとなった ダートマス会議 から60年、日本に人工知能学会が設立されてから30年の節目の年とのことで、数々の目玉企画が予定されています。昨年に引き続き開催される 人工知能学会 倫理委員会の公開討論 や、Deep learningの原型ともいわれる ネオコグニトロン の考案者である 福島邦彦先生 による 特別講演 なども行われます。 ネクストのブースでは、昨年11月から提供開始した HOME'Sデータセット や、大学との共同研究の取り組み、プロダクトの紹介などを行います。リッテルラボラトリーでは、データセットをきっかけとした共同研究など、産学連携の取り組みを積極的に行っております。データセットに関する質問や要望、研究テーマのディスカッションなどをお受けいたしますので、ご関心をお持ちの方はぜひお越しください! プロダクトとしては、レゴブロックでお部屋づくりが体験できる「 GRID VRICK 」や、あなた好みのお部屋を学習して提案してくれるアプリ「 HOME'Sヘヤサク! 」のデモを行います。 多くの方のお越しをお待ちしております!
アバター
こんにちは。HOME’SのiOSアプリ開発チームの高橋です。 WWDC2014でSwiftが発表されてから2年が経とうとしております。 Swiftは昨年末にオープンソース化され、ネイティブアプリだけでなく、サーバサイド用のフレームワークも登場するなど、動きがますます活発になってきています。 昨年度、私たちのチームではメンバーのSwift力を向上させるために、半年に渡ってチーム内勉強会を行いました。今回はその内容をご紹介したいと思います。 Swiftに対するHOME'Sアプリチームの課題 私たちの課題は、メンバーごとにSwiftの開発経験に差があることでした。 Swiftに触れる機会がないメンバーもいれば、個人でバリバリSwiftアプリを開発したメンバーもいます。 このような状況ではあるものの、メンテナンス性や今後のトレンドも考慮すると、やはり今後はなるべくSwiftを使っていきたい。どうやったら効率良く、チームのSwift力を向上できるかを考えた結果、 座学ではなく実際に手を動かして学ぶ。 実アプリへの導入イメージがつかめるようにする。 といった点から、「住まい探しアプリ開発勉強会」を開催してみることにしました。 アプリ開発勉強会の内容 やったこと まずチームをグループ分けし、Swift経験がある人をリーダーにしました。そしてグループごとに自由な「住まい探しアプリ」を考えてもらいました(どこかで見たようなUIだったり、斬新な検索方法だったり)。 仕様が決まったら、そのグループで実装を行います。期間は半年間で週1回、1〜2時間程度行いました。 またこの機会に、実際に使いそうなライブラリも試してみたかったので、APIへのアクセスにはAlamofireかAPIKitのどちらかを使ってもらいました。 使用感については後の発表会で共有しました。 リーダーとして考えたこと 私もグループのリーダーを担当しましたが、工夫としてメンバーにSwiftに関連するちょっとした課題を出してみました。 例えば、「家賃の合計値をreduceを使って計算してください。」とか「HOME'SのAPI用にAlamofireをProtocol Extensionで拡張してください。」と言った具合です。 コードを書くだけなら従来のObjective-C的に書けてしまうので、課題を設定することでSwiftを意識してもらいました。 レビュー 設計・実装をみんなでレビューしました。 実装時には気づかなかった意見が挙がり、有意義なレビュー会ができました。特にプロトコルやジェネリクスの使い所などは、他人のコードを読まないとイメージが湧かないところもあるため、とても勉強になりました。また、SwiftはObjective-Cよりも短くコードが書けることが多いため、「こうしたらもっと短くできる」「ここも短くできる」といった議論になって楽しかったです。 結果と反省 後日メンバーの感想を聞いたところ、 Swiftらしい書き方がわかってよかった。 業務で質問しにくいことを聞けてよかった。 Swift導入に対する心理的な障害が減った。 といった良い感想を得ることができました。チームとしてSwiftに対する知識はかなり向上できたと思っています。 一方で、 メンバー全員が均等にコードに触れられるよう、調整するのが難しかった。 アプリの開発には仕様決めや設計など多くの作業が必要で、作りながらSwiftを学ぶのは難しかった。 といった意見も出ました。アプリ自体の開発に時間が取られすぎないよう、仕様や大枠の設計はあらかじめ決めてしまうといいかもしれませんね。 CocoapodsやGitなど、プログラミング以前につまづくことも多かったです。勉強会前には必ず開発準備を整えてから望むようにしたいところです。 終わりに 今回、弊社で行ったチームのSwift力向上のための取り組みについてご紹介しました。 もし詳しい内容が知りたい方は、弊社では毎月もくもく会を行っておりますので、ぜひご参加ください!お待ちしております! mokumoku-ios-at-next.connpass.com
アバター
こんにちは、新卒2年目エンジニアの池田です。 今回は、先日開催されたネクストの社内イベント「第2回創民祭」のレポートをしたいと思います。 ディープラーニング・VR・tvOS など最新技術を用いたプロダクトや、 リリースに向けて鋭意開発中 のプロダクトなど見ていて楽しい出展ばかりでした。 創民祭(そうみんさい)とは 聞き慣れない言葉かと思いますが、「創民祭」は 業務内外で作ったプロダクトをみんなで発表し合うネクストのお祭り です。 創民(そうみん)は「モノ創りをする民」を表しています。 ちなみに「ソーミン」で例の小麦粉を原料とした食べ物を思い浮かべられた方は、 実際に例の物が振る舞われた第1回創民祭 の記事をご覧ください。 創民祭の様子 では早速レポートしていきましょう。 賑わってます 4月に入社したばかりの新卒社員も含め、来場者は多数。 会場には、ビール・からあげ・ピザなどパーティーの定番が揃っています。 DJブース なんと今回は DJブース も! ネクストでは最近DJの文化が盛り上がっております。 展示プロダクト紹介 さあ! ではプロダクトを紹介していきましょう。 VRアクションゲーム こちらはOculus+Kinectを使ったアクションゲームです。 自在に操れる剣と魔法で、巨大なモンスターと戦う体験ができます。 全身の動きがリンクすることで得られる高い没入感と、 巨大なモンスターが鼻先まで迫る迫力 は一見の価値があります。 弊社役員の山田 も没入しております。 このプロダクトは ニコニコ超会議 にも出展しました。 Goromi for Youtube on tvOS こちらはAppleTVのアプリです。 「Goromi for Youtube(元GoromiTube)はYoutubeのビデオをひたすら流し続けるアプリです。 世界中の聞いたこともないビデオに出会ったときは幸せを感じることができるでしょう。」 とのことで、休日ゴロ見して幸せに浸っている姿が目に浮かびますね。 iTunes Storeからダウンロードもできる ので、是非チェックしてみてください。 Goromi for Youtube GoroOtsubo 写真/ビデオ 無料 Jocker Container Service こちらは創民の名に相応しい技術に特化したプロダクトです。 「Jocker Container Serviceはコンテナ型仮想化技術を用いた社内向け開発環境提供サービスです。 利用者はたった3秒で自分だけの開発環境を手に入れることができます 。」 とのことです。下記がサービスの詳細を表した図です。 興味を持たれた方は、発表者の弊社のエンジニアkaihar4に是非連絡を取ってみてください。 ↓kaihar4のHPです kaihar4.com おそ松さんの6つ子判別器 社内屈指のはてなブロガーでもある弊社のエンジニア id:bohemian916 の出展で、 「ディープラーニングでおそ松さんの六つ子を見分ける判別器」です。 4月に入社したばかりの新卒社員も興味津々ですね! 自分も目の前で判別器が動作する様子を見たのですが、 人間でもわからないような特徴を見事に捉えて判別できていました 。 そして、人力にもかかわらず判別器を上回る正確さで、六つ子の判別を行っている id:bohemian916 も圧巻でした。 判別器の詳しい内容はこちらをご覧ください。 TwilioAPIを用いた電話でのシステム異常通知システム こちらはエンジニアna0AaooQ( http://qiita.com/na0AaooQ )によるサービスで、「Twilio」というクラウドAPIサービスを用いて、システム障害等の際に指定した電話番号に対して簡単に電話をかけたりSNS通知をするというものです。 これで「知らないうちにシステム障害が…」というトラブルが激減することでしょう! 詳しくは下記の記事をご覧ください。 他にも盛りだくさん 社外秘ですが、某ナンチャラカンチャラー・某ホニャラララランラの出展など盛りだくさんでした。 受賞プロダクト Tech賞 Tech賞は技術的に最も素晴らしいと認められたチームに贈られる賞です。 今回のTech賞は… (デデン!) 【Jocker Container Service】 でした。 ベテランの先輩たちを差し置いて新卒2年目でのTech賞。末恐ろしいですね。 山田賞(役員賞) 弊社役員の山田の心が震えたプロダクトに贈られる賞です。 今回の山田賞は… (デデデン!) 【住宅・土地統計調査データを活用したスマホ向けサービス(※ 詳細は社外秘)】 でした。 残念ながらこちらでは内容をお伝えすることができませんが、リリースに向けて絶賛準備中です。 プレスリリースによる今後の発表を楽しみにしていてください。 最優秀賞 そしていよいよ最優秀賞です。 今回の最優秀賞は… (デデデデン!) 【家族と一緒に住まい探しができるサービス(※ 詳細は社外秘)】 でした。 残念ながらこちらも内容をお伝えすることができません。 プレスリリースによる今後の発表を楽しみにしていてください。 出展プロダクトに関するレポートは以上です。 少しでも興味をもっていただければ幸いです。 最後に 先程までVRアクションゲームに没入していた役員の山田 が最後に締めて、創民祭は大盛況のうちに閉会しました。 人が作ったものに見たり触れたりするとその人の熱が伝わってきますね。 その熱に触れて 「自分も何か作りたい!」 と強く感じました。 今回は2回目の開催でしたが、1回目に比べて確実にパワーアップしていると感じました。 創民祭は、これからも定期的に開催する予定なので、この場を借りてみなさんに情報をお伝えしていきたいと思います。 ではでは。
アバター
こんにちは。HOME'SのiOSアプリ開発チームの塙です。HOME'Sアプリの最新版(Ver.3.10)で追加された Flyover は、ある新卒※のアイデアから実現したものでした。この話を書くことで弊社のアプリチームがどんな雰囲気なのか感じ取ってもらえればと思います。 ※ 2016年4月1日を以って新卒2年目になりました! Flyoverとは iOS6から標準マップアプリで提供されていた建物などを3Dで表示する機能です。iOS7くらいから日本の主要都市にも対応を始め、今では国内の13都道府県に対応しています。iOS9からはMKMapKitに追加され、サードパーティ製アプリでもFlyoverを実装することができるようになりました。 アイデアが採用される アプリチーム(iOSとAndroid)には 「アイデアボード」 というJIRAで管理されたかんばんボードがあり、そこではメンバーの誰もがアプリに追加してみたい機能や改善したい箇所などを投稿できます。今まで追加された機能も、このアイデアボードから実現したものがいくつもあります。 アイデアがこんなにたくさん!チームのみんなが日々投稿してます! 新卒の私は技術力もなく仕事もうまくこなせないので、素人なりの新鮮なアイデア力で勝負しようと思い、定期的にこのアイデアボードに投稿を行っていました。アプリを触っていて「こうだったらいいのにな」と思った時や、iOSのアップデートで新しい機能が実装できるようになった時は仕事の合間に簡単なモックを作成して一緒に載せたりもしました。 そしてある日リーダーの方から 「アイデアボードにあったFlyoverの件だけど、採用になったから今すぐやってみない?」 という声をかけてもらいました。 iOSアプリのリーダー、プ◯ジェクトXみたいでカッコイイ… 企画立案からアサイン 私はもともと大学でユーザーインタフェースの勉強をしていたので、企画からモノづくりをしたい気持ちがあり、上司にも伝えていました。そのこともあり、Flyoverのプロジェクトは仕様書の作成から担当させてもらえることになりました。 もちろん仕様書の作成などやったこともないので何をしたら良いのかわからなかったのですが、企画とデザイナーの先輩方に沢山フォローしてもらい、なんとか完成させることができました。アプリチームはプロダクト的にも 企画、デザイナー、開発のチームの距離感が近く 、いつもコミュニケーションを密にとっているからこそ可能なのかなと思いました。 この写真はやらせですが笑 いつもこんな感じで話し合ってます! (写っているのは各職種の先輩方です!) 仕様を考える上で普段目にしないユーザーの行動や数値を扱い、自分たちの開発したものがこんなにも多くのユーザーに影響を与えているのかと痛感しました。また、画面の構成も社内の人にABテストをしてもらって決めました。この時もたったボタンひとつの配置が、開発する側と使う側で考えることに大きな違いがあることに気付かされました。 もちろん実装も自分で 自分の力不足のせいではありますが、実装に入るまでにかなりの時間を費やしてしまいました。正直な気持ち「やっとコードが書ける…」と思ってしまいましたが、得るものは大きかったと思います。 実装に関してはそこまで大きな労力のかからないものでしたが、企画から自分でやってきた分、実装の時の責任感はいつにも増して大きく感じました。 ちなみにご自身のマップをFlyoverに対応させたい場合はこの1行を追加すればすぐにできます。 対応地域 も増えてきて、見ているだけでも楽しいこの機能を是非追加してみてください。 mapView.mapType = .SatelliteFlyover // or .HybridFlyover HOME'SアプリのFlyover画面。「3D」をポチっとしてみてください! いろいろやってみて Flyoverは住まい探しをする上で 「周辺環境を知りたい」という声 が多いことからアイデアを出したものでした。そのユーザーの為に考えたアイデアを一から自分で作り、実際にリリースされる機会は本当に貴重なものです。また、それを可能にしてくれたアプリチームの環境にはとても感謝しています。 今回のプロジェクトで普段エンジニアとして目にすることが少ない数値や、疎かになりがちなユーザー目線に触れることがきたので、今後の開発に活かしていきたいです。そしてこれからもチーム一丸となって、ユーザーに役立つ、楽しいアイデアに溢れたHOME'Sアプリを創っていきます! アプリチームの爆発的な活躍に乞うご期待!
アバター
<!-- p { style="line-height: 2; margin: 0.5em 0px; padding: 0px; color: #3d3f44; font-family: 'Helvetica Neue', Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; } -->   こんにちは、HOME'Sアプリのデザインを担当しているこばやしです。 今回は「 マテリアルガイドラインの上手な使い方 」をお話したいと思います。   今回のテーマは、 マテリアルガイドラインからは、手段よりも本質を読み取ろう 分解すると、 マテリアルガイドラインに載っている手段を真似るでは不十分 本質を自分なりに解釈してみる その解釈から、手段を検討して、アプリに適応していく 以上をデザイナーは留意したいね、という内容になります。 どうしてこれらが大事なのか、それについて 「インタラクション」 をテーマにお話します。 ※ここでの解釈はHOME'Sアプリにおけるものなので、すべて正解ではないです     インタラクション なぜインタラクションなのか 前編 でもお伝えしましたが、マテリアルガイドラインの3つのデザインの原則の1つである「意味のあるアニメーション」として、インタラクションは非常に重要で、優れたユーザー体験をつくる デザインの要素なので、今回テーマとしてお話します。   リップル効果 引用元: Material Design Guidlines マテリアルデザインのアニメーションといえば、タップしたときに波紋のように広がるアニメーションです。これはタップした場所からエフェクトを付けることで、画面のどこをタップしているのかがわかりやすくなります。 入力があった際に、画面内でアクションに応じた返答を返してあげることで、ユーザーへの注意喚起や、UIの理解を助ける働きをしてくれます。   連続性 引用元: Cards Swipe Animation – MaterialUp ビュー・画面の切替りの話がでましたが、そこでもインタラクションが重要になります。これまでのWebでは常識であったページ遷移は 急にページが切り替わる・閉じてしまうなど動きでしたが、これは明らかにバーチャルな世界でメタファーとは異なります。 このインタラクションを工夫することで、現実的な動きに置き換えることができます。急に画面が切り替わるのではなく、タップした次のページには要素を維持したまま遷移させることで、ユーザーは何が起こっているのかを明確に把握しやすくなります。     次に、HOME'Sアプリではどのように取り入れているのかお話します。     インタラクションを考える時、HOME'Sアプリが注意したこと OSバージョンのデフォルトを考える マテリアル対応を進めていくにあたり無視できないのが、OSバージョン毎の扱いです。ここまで説明してきたマテリアルデザインですが、端末デフォルトで搭載しているのはバージョンOS5.0以上になります。 現在のOSシェアはまだまだ4.x系が多く、そういったユーザーはあまり普段からこのマテリアルデザインのインタラクションに慣れていません。つまり、新しいユーザー体験になります。    ユーザーに余計な学習をさせない HOME'Sアプリでは OS5系以上では、リップル効果のインタラクションを採用 OS4系以下では、デフォルトのインタラクションを採用 としています。 様々なアプリを使う中で、HOME'Sアプリだけインタラクションが他のアプリより明らかに異なると「ユーザーの理解を助けるためのアニメーション」が、かえって驚かれてしまったり、余計なことを考えることに繋がるのではないか、という考えのもと上記のような対応をしています。   Google純正アプリを見てみる ご存知の通りGmail、Youtubeなどそれぞれ開発チームが異なるので、マテリアルガイドラインの解釈の仕方もそれぞれ微妙に異なっていて参考になります。 OS5系以上では、リップル効果のインタラクションを採用 OS4系以下では、デフォルトのインタラクションを採用 純正アプリでも未対応です。 というより、おそらくあえてやってないのかなと思います。繰り返しになりますが、マテリアルガイドラインの本質は全アプリのUI統一をすることではなく、ユーザーがアプリを使うときにスムーズに使えるよう基準を設けることだと思うので、Android4.x以下の端末の場合は従来のインタラクションのままがこの場合「筋が通っている」ということなのかもしれません。   まとめ マテリアルガイドラインからは、手段よりも本質を読み取ろう 大切なのははじめにお伝えしたこれです。   マテリアルガイドラインには、マテリアル対応するための手段や方法・事例が具体的に記されていますが、マテリアルデザインの本領を発揮させるためには、手段だけではなく、本質を各自が解釈して各々のサービスにどのように適応していくのが最良かを考えることが大切だと思います。   そういった意味では、デザイナーがやらなければならないことに何も変わりはないですね。上手に適応させてより使いやすいアプリを目指しましょう。   そんなマテリアルデザインですが、対応を進めていくとHOME'Sではある問題を抱えました。次編ではその内容と解決手段についてお話しします。
アバター