Sansan Tech Blog

Sansanのものづくりを支えるメンバーの技術やデザイン、プロダクトマネジメントの情報を発信

【Techの道も一歩から】第19回「itertoolsを使おう」

こんにちは。 DSOC R&D グループの高橋寛治です。

桜の花びらが散り春の時候を感じる今日このごろ、スマブラだけでなくコーディングの季節もやってきたなと思っております。

意気込んでコーディングを始めたときに、たとえば2階層のリストを1階層に変形したり、条件に沿うものだけをリストから抽出したりする場合に、自分で実装してしまいがちです。

そのようなリストの各要素に対する処理について、高速かつメモリ効率のよい実装である itertools が Python の標準モジュールとして実装されています。 今回はこの itertools や言語処理に取り組んでいる際の適用例などを紹介します。

イテレータ

イテレータとは、公式マニュアルに書かれている通りですが、データの流れを示すオブジェクトです。 Pythonの内部処理としては、イテレータオブジェクトの __next__() メソッドが呼ばれる、もしくは next() に渡された場合に、次のデータを返します。

実際のコードを見てみましょう。 itertools.count というのは、start で値が始まり、呼び出すごとに step の値分加算された値を返すというイテレータです。

>>> import itertools
>>> iter_count = itertools.count(start=0, step=1):
count(0)
>>> iter_count.__next__()
0
>>> iter_count.__next__()
1
>>> next(iter_count)
2
>>> for c in itertools.count(start=0, step=1):
...:     if c > 2:
...:         break
...:     print(c)
0
1
2

ここではいったん for で読み取る場合には、 __next__() が呼ばれると考えてください。 呼ばれるごとに加算された値が返っていることがわかるかと思います。 この itertools.count ですが、次のコードとほぼ等価です(公式マニュアルより引用)。

def count(start=0, step=1):
    n = start
    while True:
        yield n
        n += step

ここで yield 式が出てきました。 これは、 next()__next__() が呼ばれるたびに、 yield で指定された値を返します。 上の例ですと、 while による無限ループ内で yield が記されており、 next() のたびに n += stepyield n を繰り返します。 このように yield 式を持つ関数は、ジェネレータと呼ばれます。

続きを読む

【ML Tech RPT. 】第6回 不均衡データ学習 (Learning from Imbalanced Data) を学ぶ (3)

f:id:ssatsuki040508:20181210005017p:plain
DSOC 研究員の吉村です。最近はシーバスフィッシングにハマっています。長らく釣れない日々を送っていたのですが、つい最近久しぶりに釣り上げてから、調子がややよくなってきました。

さて、前置きはこのくらいにして、今回も不均衡データ学習の話です。今回は、不均衡データに対して異常検知手法を用いる方法について説明をします。ちなみに前回、前々回の記事をまだ読まれていない方はそちらから見ていただけると嬉しいです。
buildersbox.corp-sansan.com
buildersbox.corp-sansan.com

不均衡データ学習に異常検知手法を用いる場合の仮定

f:id:ssatsuki040508:20190425211752j:plainf:id:ssatsuki040508:20190425211806j:plain
二次元平面上にデータ点をプロットした様子の例。
(左図) 分類問題として対処すべきと考えられるデータの分布。
(右図) 異常検知問題として対処すべきと考えれるデータの分布。
前々回の記事から、不均衡データ学習におけるアプローチの一つとして異常検知手法を紹介していますが、異常検知手法は不均衡データ学習に対する一般的な対処法ではありません。
不均衡データ対策として異常検知手法が有効に働くのは、少数派のデータ点が特徴量空間上でクラスタを作っていない場合であると考えられます。この時には、少数派のデータを"滅多にない"、"普通ではない"データ(つまり、異常データ)と考えることで異常検知手法の適用ができます。
ここで私が言いたいことは、あくまでも不均衡データ学習を異常検知の問題設定とみなせるときにのみ、異常検知手法が威力を発揮するのであり、異常検知手法は不均衡データ学習全般に対する汎用的な対処法ではないということに注意すべきであるということです。本記事の趣旨は不均衡データ学習に用いるための手法を知ることなので、今回は時系列ではない異常検知問題に対処するための手法についていくつか紹介します。

続きを読む

▲The Prism of Creativity ▽ vol.4 ハイブリッド型ブレインストーミング[心理学編]

f:id:sansan_nissy:20190107153214j:plain
こんにちは、DSOC 研究員の西田です!
最近は、チョーカーを買いましたが、首につける気にはなれず、腕に巻いています。ちょうどいい感じです。もちろんCから始まるブランドのものです。


さて、少し間が空いてしまったので、まずは前回のブログを復習していきましょう!

前回のブログでは、クリエイティブなアイデアを考えるためには、1人で考える時間が重要であるという研究を紹介しました。1人でいるときに、脳のDefault Mode Networkが活発になり、アイデアを思いつきやすくなるというメカニズムによるものです。そして、最後に仕事などのブレインストーミングはチームで行われることが多いことから、「1人でアイデアを考えるのが良いのか、チームで考えるのが良いのか?」という問いかけをしました。

そして、その答えは、Sansan Innovation Project 2019 の「Think Different とは何か?」というセッションで予防医学者の石川善樹氏と経営学者の永山晋氏とともに発表するという、記事広告感溢れる展開で終えたのが前回のブログでした!(笑)

ということで、今回はそのイベントの内容を書こうと思っていましたが、Logmiさんの記事や弊社オウンドメディアBNLのレポートが既にアップされてます! 前回から結論が気になっていた方はこちらを読んでみてください!

bnl.media


logmi.jp

簡単にまとめると、下記の通りです。

  1. 脳科学の研究から、「生成」「選定」「評価」のプロセスでは、それぞれ「Default Mode Network」「Salience Network」「Executive Network」と呼ばれる脳の異なる部位が活性化することがわかっている
  2. 凡人の脳はこの3つのネットワーク同士の結びつきが弱いのに対し、「天才の脳」では3つが強く結びついている
  3. アイデアの「生成」に必要な「Default Mode Network」は1人の時に活発になりやすく、アイデアの「選定」に必要な「Executive Network」はチームでいるときに活発になりやすい
  4. したがって、1人の時にアイデアの「生成」や「選定」を行い、複数のアイデアを結びつけるような内省のプロセスを踏まえた上で、複数人のミーティングに参加し、アイデアの「評価」を行うことで「天才の脳」に近づける

上記の結論と前回のブログの内容を踏まえると、チームで考えるタイミングを気をつけた方がいいということになります。それでは、どういうタイミングでチームで考えるのがいいのでしょうか? 今回はこの問いに答えるべく、ブレインストーミングに関する研究(Korde and Paulus, 2017)*1をご紹介します。

*1:Korde, R., & Paulus, P. B. (2017). Alternating individual and group idea generation: Finding the elusive synergy. Journal of Experimental Social Psychology, 70, 177-190.

続きを読む

【つながりに効く、ネットワーク研究小話】vol.8 「信頼」か、「しがらみ」か?――社会関係資本のダークサイド

f:id:s_yuka:20181211105445j:plain Sansan DSOC研究員の前嶋です。「つながりに効く、ネットワーク研究小話」の第8回です。

4月も終わりに差し掛かり、新しく出会った人たちとの「よそよそしさ」も抜けてきて、代わりに「親しみ」が顔を覗かせる頃ではないでしょうか。

はじめに:社会関係資本とは

親密な関係性はある種の利益をもたらします。社会関係資本(social capital)とは、信頼や互酬性の規範、ネットワークのことです。その定義は論者によって様々ですが、「人々の関係性から何らかの利益が創発する」という共通したコンセプトを持っています。

社会関係資本は、それを「保有」する主体が誰かによって、3つのレベルに分けることができます。各レベルについて、利益をもたらす条件と主な論者(とその主著)を整理します。

  • ミクロ(個人)レベル
    • 条件:ネットワークによってアクセスできるリソース、ネットワーク上のポジション
    • 主な論者:ナン・リン『ソーシャル・キャピタル―社会構造と行為の理論』、ロナルド・バート『競争の社会的構造―構造的空隙の理論』)
  • メゾ(集団)レベル
    • 条件:集団内部のネットワークの疎密、特定化された信頼
    • 主な論者:ジェームズ・コールマン『社会理論の基礎』
  • マクロ(国家・地方自治体)レベル
    • 条件:集団同士の織りなすネットワーク、一般化された信頼
    • 主な論者:ロバート・パットナム『哲学する民主主義』『孤独なボウリング』

今回の記事では、主にメゾレベル、つまり、集団内部での社会関係資本の持つ負の側面について紹介します。

社会関係資本のライトサイド

まずは社会関係資本の「良い面」に触れておきましょう。言うまでもなく、チームの結束力はパフォーマンスを底上げします。BNLの記事でも紹介している通り、ジェームズ・コールマンは、密で閉鎖的なネットワークが集団内の信頼を醸成したり、規範を強化すると論じています(Coleman 1988)。さらに最近では、そのような凝集的なネットワークは、新規性の高い情報をより多く流通させることにも役立つことも示唆されています(Aral 2016)。

また、社会関係資本は健康に対しても良い影響を及ぼすことが知られています。タバコを吸わないように心がけることは個人の営みですが、「路上喫煙禁止」といった健康に関わるルールの策定やその監視は、個人間の協力が必要な社会的営みであるからです(Villalonga-Olives and Kawachi 2017)。健康という一見とても「私」的な事柄に対して、個人を超えた「つながり」が影響するというのは、非常に興味深い現象です。

社会関係資本のダークサイド

しかし、集団の保有する社会関係資本には、負の側面も存在します。この負の側面に初めて言及したのが、アレハンドロ・ポルテスです。ポルテス曰く、社会関係資本には次のような負の側面があると考えられます(Portes 1998)。

外部者の排除(exclusion of outsiders)

エスニック集団や職業集団など、同じような属性を共有した集団が強いつながりを持っていると、異なる属性を持った人々を排除するように作用する場合があります。

集団メンバーへの過度な要求(excess claims on group members)

互酬性の規範が強い集団の場合、メンバーのうちの誰かが(例えば経済的に)成功した場合、その人に次々と職の斡旋や金銭的援助を無心する人々が現れることがあります。

個人の自由の制限(restrictions on individual freedoms)

コールマン流の議論によれば、密で閉鎖的なネットワークによって社会規範が強化される理由に、監視コストが下がることが挙げられますが、それはプライバシーの侵害や規範の押しつけを招き、個人の自由を制限するという事態にもつながります。

下方平準規範(downward leveling norms)

集団の中には、主流の社会規範への反抗心によって共同性が担保されているような集団も存在するかと思います。そのような集団では、メンバーの成功を阻害するような振る舞いがしばしば観測されます。結束が強すぎると「一抜け」を阻止しようとすると言ってもよいでしょう。

最近、組織コミュニケーションという観点から見た社会関係資本の負の側面に関してレビューした論文が出ています(Pillai et al. 2017)。著者らは、「個人的学習の禁止(the inhibition of individual learning)」「構造的調整の先延ばし(the postponement of structural adjustments)」「企業の境界の曖昧化(the blurring of firms’ boundaries)」といったデメリットを挙げています。詳細が気になる方は、元論文を参照してみることをお勧めします。

「信頼」と「しがらみ」のあいだで

健全な社会関係資本は信頼を生み、集合的行為を効率化する作用があります。しかしながら、「信頼」が「しがらみ」に転化する恐れも、否定できません。社会関係資本の「腐敗」に特徴的なのは、閉鎖性が高いが故に外部の視点が供給されず、腐敗していることそれ自体に気づきにくいことでしょう。

重要なのは、「閉鎖」と「開放」のバランスです。結束的なチームのパフォーマンスを長期間持続させたい場合、別のクラスタへの橋渡しの回路を意識的に用意しておくか、あるいは近年になってロナルド・バートが提案しているように、周期的に閉鎖と開放のモードを切り替えることが必要かもしれません(Burt and Merluzzi 2016)。

【参考文献】

  • Aral, S. (2016). The future of weak ties. American Journal of Sociology, 121(6), 1931-1939.
  • Burt, R. S., & Merluzzi, J. (2016). Network oscillation. Academy of Management Discoveries, 2(4), 368-391.
  • Coleman, J. (1988). Social Capital in the Creation of Human Capital. American Journal of Sociology, 94, 95-120.
  • Portes, A. (1998). Social capital: Its origins and applications in modern sociology. Annual review of sociology, 24(1), 1-24.
  • Pillai, K. G., Hodgkinson, G. P., Kalyanaram, G., & Nair, S. R. (2017). The negative effects of social capital in organizations: A review and extension. International Journal of Management Reviews, 19(1), 97-124.
  • Villalonga-Olives, E., & Kawachi, I. (2017). The dark side of social capital: A systematic review of the negative health effects of social capital. Social Science & Medicine, 194, 105-127.

【Intern CV Report】超解像の歴史探訪 -SRGAN編-

f:id:S_aiueo321:20190404193803p:plain

こんにちは,DSOC R&D インターン生の内田です. 時が流れるのは早いものでもう4月末,連載も2回目を迎えました. もう少しで平成も終わってしまうので,平成生まれの僕は少し寂しさを感じています.

さて,前回の記事では2016年に発表された超解像モデルについて紹介しました. 今回は2017年にフォーカスしたいと思います. その中でも特に有名なSRGAN[*1]についてまとめます. なお,本記事では以前に紹介した手法や略語が前置き無しに登場する場合がありますので,不明な点がございましたら過去の記事をご参照ください. buildersbox.corp-sansan.com buildersbox.corp-sansan.com

GAN

SRGANの説明に入る前に,流行りのGANについて触れておきます. ご存知の方は読み飛ばしていただければと思います.

GANはGenerative Adversarial Networkの略であり,日本語に訳すと「敵対的生成ネットワーク」となります. 「生成モデル」を「敵対的学習」によって獲得する枠組みであるためこのような名前がついています. 「生成モデル」とは,データを生成する確率分布を学習し新たなデータをサンプルできるモデルを指します. 「敵対的学習」とは,生成器  G を学習するために,識別器  D を同時に学習する方法を指します.

 Dには学習データ及び  G の生成結果を入力し,入力が学習データからサンプリングされている確率を出力します. ざっくり言うと,  D は「本物っぽさ」を出力します.  D の学習では,学習データの分布  p_\mathrm{real} からサンプルされた入力に対して 1,生成結果の分布  p_\mathrm{fake} からサンプルされた入力に対して 0を出力するようにしたいため,次の学習基準 \mathcal{C}_Dを最大化すればよいと言えます. $$ \mathcal{C}_D = \begin{cases} \log D(\boldsymbol{x}) & \text{if $\boldsymbol{x} \sim p_\mathrm{real}$} \\ \log \left( 1-D(\boldsymbol{x}) \right) & \text{if $\boldsymbol{x} \sim p_\mathrm{fake}$} \end{cases} $$

 G は,  D を間違えさせるようなデータを生成することを目的とします. したがって, G の学習では,何らかの分布 p_{\rm z}からサンプルされた入力ベクトル  \boldsymbol{z}に対して,次の学習基準 \mathcal{C}_Gを最小化すればよいと言えます. $$ \mathcal{C}_G = \log(1-D(G(\boldsymbol{z}))) \text{where $\boldsymbol{z} \sim p_\mathrm{z}$}$$

 \boldsymbol{x} \sim p_\mathrm{fake}のとき \boldsymbol{x}\ = G(\boldsymbol{z}) であることに注目して,  \mathcal{C}_G \mathcal{C}_D をまとめると次の目的関数 V(D, G)のようになります. ただし, D G とで最適化の方向が異なるため,GANの学習は V(D, G)のmin-max最適化として定式化されます. $$ \mathop{\rm min}\limits_{G}\mathop{\rm max}\limits_{D} V(D,G) = \mathbb{E}_{\boldsymbol{x} \sim p_{\rm data}}[\log D(\boldsymbol{x})] + \mathbb{E}_{\boldsymbol{z} \sim p_{\rm z}}[\log (1-D(G(\boldsymbol{z})))] $$

ここで紹介したのは,Vanilla GANという最もベーシックな手法です. SRGANをはじめとするGANの派生では誤差関数にMSE(Mean Square Error)などの項も入ってくるため,必ずしも上記の形をとる訳ではありませんが, D Gを逆方向に最適化するというお気持ちは変わりません.

SRGAN

SRGAN(Generative Adversarial Network for Super-Resolurion)は超解像にGANを初めて適用したモデルで,論文のタイトルに「Photo-realistic」とあるように,従来手法に比べて結果の知覚品質が高く,自然であるとして有名です. 近年提案されている超解像モデルの多くがSRGANをベースとしていて,直近のECCV2018に併設されたPIRM Challenge on Perceptual Super Resolution[*2]においても,SRGANの拡張であるESRGAN[*3]が知覚品質を競うトラックで優勝を納めています.

以下では,SRGANの構造の解説と実装,GANを導入する効果について実験を行います. コードは下記で公開しておりますので,不明な点や詳細はぜひこちらでご覧ください.「Issue」を投げていただいたら,喜んでお受けします. github.com

また,実装にあたり次のレポジトリを参考にしています.

生成器

SRGANの生成器はResNet[*4]を参考にしており,識別器を伴わずに学習した場合SRResNetと呼ばれます. ResNetは,畳み込みの入出力を足し合わせて出力するResidual Blockを積み重ねたネットワークです. SRGANでも同様に,次のようなResidual Blockを積み重ねた構造をしています.

f:id:S_aiueo321:20190408132248p:plain
SRResNetの構造(x4)
ここでは,図中の各ブロックを定義した後,生成器を組んでいきます.

Residual Block

畳み込み,バッチ正規化,活性化を直列に適用するため,nn.Sequentialを用いて1つのモジュールにまとめることができます. forward()で,入力xとコンストラクタで定義したモジュールの出力self.net(x)を足し合わせて返り値とします.

class ResidualBlock(nn.Module):
    def __init__(self, channels):
        super(ResidualBlock, self).__init__()
        self.net = nn.Sequential(
            nn.Conv2d(channels, channels, kernel_size=3, padding=1),
            nn.BatchNorm2d(channels),
            nn.PReLU(),
            nn.Conv2d(channels, channels, kernel_size=3, padding=1),
            nn.BatchNorm2d(channels),
        )

    def forward(self, x):
        return self.net(x) + x

Upsample Block

ここでは,前回紹介したESPCN同様,Subpixel Convolutionを用います. まず,入力特徴マップを倍率upscale_factorの2乗になるよう,畳み込みを用いてチャネル方向に拡張します. 次に,拡張した特徴マップを再配置します.PyTorchではnn.PixelShuffleとして用意されているのでそちらを用います. 最後の活性化も含め,nn.Sequentialを用いて1つにまとめます.

class UpsampleBLock(nn.Module):
    def __init__(self, in_channels, upscale_factor):
        super(UpsampleBLock, self).__init__()
        self.net = nn.Sequential(
            nn.Conv2d(in_channels, in_channels *
                      (upscale_factor ** 2), kernel_size=3, padding=1),
            nn.PixelShuffle(upscale_factor),
            nn.PReLU()
        )

    def forward(self, x):
        return self.net(x)

全体

SRResNetにはSkip-connectionがあり,単純にnn.Sequentialでまとめられないため,図のようにHead,Body,Tailの3部分に分けます. Residual Blockは16回,UpsampleBLockはint(log2(upscale_factor))回繰り返すように内包表記で記述します. また,出力はnn.Tanhを用いて (-1, 1)に正規化し,forward時に (0, 1)にスケーリングします.

class Generator(nn.Module):
    def __init__(self, scale_factor=4):
        super(Generator, self).__init__()
        self.head = nn.Sequential(
            nn.Conv2d(3, 64, kernel_size=9, padding=4),
            nn.PReLU()
        )
        self.body = nn.Sequential(
            *[ResidualBlock(64) for _ in range(16)],
            nn.Conv2d(64, 64, kernel_size=3, padding=1),
            nn.PReLU()
        )
        self.tail = nn.Sequential(
            *[UpsampleBLock(64, 2) for _ in range(int(log2(scale_factor)))],
            nn.Conv2d(64, 3, kernel_size=9, padding=4),
            nn.Tanh()
        )

    def forward(self, x):
        x = self.head(x)
        x = self.body(x) + x
        x = self.tail(x)
        return (x + 1) / 2

*1:Ledig, Christian, et al. "Photo-realistic single image super-resolution using a generative adversarial network." Proceedings of the IEEE conference on computer vision and pattern recognition. 2017.

*2:Blau, Yochai, et al. "The 2018 PIRM Challenge on Perceptual Image Super-Resolution." European Conference on Computer Vision. Springer, Cham, 2018.

*3:Wang, Xintao, et al. "ESRGAN: Enhanced super-resolution generative adversarial networks." European Conference on Computer Vision. Springer, Cham, 2018.

*4:He, Kaiming, et al. "Deep residual learning for image recognition." Proceedings of the IEEE conference on computer vision and pattern recognition. 2016.

続きを読む

行ってきました re:Invent 2018 (Day 4 Keynote 2は開発者歓喜、からのre:Play Party編)

またまたお久しぶりです、 id:matetsu です。JAWS DAYSのレポートを間に挟んだので、やった気になったのと、多忙を言い訳に後ろ倒しにしてしまっていたのとが重なって、こんなに遅くなってしまいました。もうすぐre:Invent 2018の開催から半年が経とうとしています。どこよりも遅いレポートのラストスパート、いってみたいと思います。(平成のうちに終わるのか?)

爪痕の完成形

程々のお酒で気持ちよく眠りについたので、余裕を持って起きられました。朝食もゆっくり摂れ、コーヒーを持ってKeynoteの開場へ。

この日もまたお絵かき広場がリセットされていて、全然人もいなかったので、のびのびと描かせていただきました。全部見て頂いてた方にはわかると思いますが、確実に成長が見られます。目立つしバランスも取れるようになってきてるし、と自画大絶賛。

いいねー、と満足して写真を撮ろうと思っていたら他の参加者のかたが写真を撮ってくれるというので、お言葉に甘えて。

f:id:matetsu:20181129072244j:plainf:id:matetsu:20181129072256j:plain
我ながらよく描けた

次の日は帰国日なので、これが最後の集大成。大満足です。少しはEightを世界に広められたでしょうかねw

続きを読む

© Sansan, Inc.