juman++を利用して分かち書き

ひとまずの目標がrnnlmを作ってみることなので、その準備として日本語の文書を渡してそれを形態素ごとに区切って出力するやつを作っておきたいです。

環境を汚したくないのでdocker内にjuman++をインストールします

FROM ubuntu:17.10

RUN apt-get update
RUN apt-get install -y git wget build-essential libboost-all-dev

RUN wget http://lotus.kuee.kyoto-u.ac.jp/nl-resource/jumanpp/jumanpp-1.02.tar.xz
RUN tar Jxf jumanpp-1.02.tar.xz
RUN cd jumanpp-1.02 && ./configure && make && make install

これは

docker build . -t jumanpp

みたいな感じでイメージを作成できます

イメージを作成したら

docker run -d -it --name jumanpp-container jumanpp

みたいな感じでコンテナを起動しておきます

すると

$ echo "吾輩は猫である。" | docker exec -i jumanpp-container jumanpp

吾輩 わがはい 吾輩 名詞 6 普通名詞 1 * 0 * 0 "代表表記:我が輩/わがはい カテゴリ:人"
は は は 助詞 9 副助詞 2 * 0 * 0 NIL
猫 ねこ 猫 名詞 6 普通名詞 1 * 0 * 0 "代表表記:猫/ねこ 漢字読み:訓 カテゴリ:動物"
である である だ 判定詞 4 * 0 判定詞 25 デアル列基本形 15 NIL
。 。 。 特殊 1 句点 1 * 0 * 0 NIL
EOS

みたいな感じで実行できます。


やりたいのは分かち書きなので、適当にシェルを書きます

#!/bin/bash

for line in $(cat -)
do
    echo "$line" | docker exec -i jumanpp-container jumanpp | while read output
    do
      if [ "${output}" != "EOS" ]; then
          word=$(echo ${output} | cut -d " " -f 1)
          if [ "${word}" != "@" ]; then
              result="${result} ${word}"
          fi
      else
          echo $result
      fi
    done
done

これをwakachi.shとか名前をつけて保存しておきます。

吾輩は猫である。
名前はまだ無い。
どこで生まれたかとんと見当がつかぬ。

みたいなファイルをテストのために用意しました

$ cat test.txt | ./wakachi.sh 
吾輩 は 猫 である 。
名前 は まだ 無い 。
どこ で 生まれた か とんと 見当 が つか ぬ 。

こんな感じで出力できました。

batch, epochについて学ぶ

1回のパラメータ更新のために利用するデータの数をbatch_size,
データを何周するかをepochと呼ぶみたいです

前回は簡単のためbatch_size = 1, epochs = 1 としましたが、現実的には両方1というのはあまりないと思うので前回のプログラムを修正してbatch_sizeとepochsに対応できるようにします。

dynamic_rnnのinputは [batch_size, max_len, input_size]なshapeなので、batch_size = 5, max_len = 3, input_size = 1なら

xs = [ [[1], [2], [3]],
       [[4], [5], [6]],
       [[7], [8], [9]],
       [[0], [0], [0]],
       [[1], [1], [1]] ] 

な感じで渡してやる必要があります

また、outputは [batch_size, max_len, cell.output_size] なshapeなので今回は上記xsと同じような形になります

output = [ [[1], [4], [7]],
           [[2], [5], [8]],
           [[3], [6], [9]],
           [[9], [9], [9]],
           [[8], [8], [8]] ] 

このとき、[ [1], [4], [7] ] は xsの [ [1], [2], [3] ] に対応していて、xsの1を入力したときの出力が1, 2を入力したときの出力が4, 3を入力したときの出力が7 となっているっぽいです。

今回の例では最後の入力を与えたときの出力がほしいので、outputの右端の列をもらうために、output[:, -1, 0]としています

まとめると、下記な感じになります。

import random
import tensorflow as tf
sess = tf.Session()

def generate_train_data(n):
    train_x = []
    train_y = []
    for i in range(n):
        xs = [random.random() * 10 for j in range(max_len)]
        ys = sum(xs)
        train_x.append(xs)
        train_y.append(ys)
    return train_x, train_y

size = 1
rnn_cell = tf.nn.rnn_cell.BasicRNNCell(num_units=size, activation=tf.nn.leaky_relu)

n_batch = 5
epochs = 4
max_len = 3
data_size = 1000

x = tf.placeholder(tf.float32, shape=[n_batch, max_len, size])

output, state = tf.nn.dynamic_rnn(rnn_cell, x, dtype=tf.float32)

y = tf.placeholder(tf.float32, shape=[n_batch])

loss = tf.reduce_mean(tf.square(y - output[:, -1, 0]))

optimizer = tf.train.GradientDescentOptimizer(0.0001)
train_step = optimizer.minimize(loss)

init = tf.global_variables_initializer()
sess.run(init)
losses = []
n_batches = int(data_size/n_batch)
x_train, y_train = generate_train_data(data_size)
for epoch in range(epochs):
    for i in range(n_batches):
        min_ix = i * n_batch
        max_ix = (i+1) * n_batch
        xs = x_train[min_ix:max_ix]
        # shape [batch_size, max_len, input_size]
        # xs = [ [[1], [2], [3]],
        #        [[4], [5], [6]],
        #        [[7], [8], [9]],
        #        [[0], [0], [0]],
        #        [[1], [1], [1]] ] なイメージ
        xs = [ [[xxx] for xxx in xx] for xx in xs]
        ys = y_train[min_ix:max_ix]
        sess.run(train_step, feed_dict={x: xs, y: ys})
        if i % 100 == 0:
            losses.append(sess.run(loss, feed_dict={x: xs, y: ys}))

print('vars : ', sess.run(rnn_cell.variables[0])) # RNNのウェイトを表示してみる
print('losses : ', losses)


結果は

vars :  [[ 1.0746733 ]
 [ 0.92348057]]
losses :  [138.32841, 0.81912673, 0.57693189, 0.40475434, 0.29114446, 0.1994734, 0.14868297, 0.098647617]

な感じでした

dynamic_rnn を使ってみる

dynamic_rnn は前回のinference相当の事をやってくれるらしいです。

In [47]: def inference(x, max_len):
    ...:     state = initial_state
    ...:     for i in range(max_len):
    ...:         (output, state) = rnn_cell(x[i], state)
    ...:     return tf.squeeze(output)

あと、前回reluを使いましたが変数の値がマイナスになった途端にoutputが0になっちゃうのでleaky reluとかを使ったほうが良さそうでした。

その辺を踏まえて、前回の足し合わせをdynamic_rnnを使って書き直してみました。

import random
import tensorflow as tf
sess = tf.Session()

size = 1
rnn_cell = tf.nn.rnn_cell.BasicRNNCell(num_units=size, activation=tf.nn.leaky_relu)

n_batch = 1
max_len = 3

x = tf.placeholder(tf.float32, shape=[n_batch, max_len, size])

output, state = tf.nn.dynamic_rnn(rnn_cell, x, dtype=tf.float32)

y = tf.placeholder(tf.float32, shape=[])

loss = tf.reduce_mean(tf.square(y - output[-1, -1, -1]))

optimizer = tf.train.GradientDescentOptimizer(0.0001)
train_step = optimizer.minimize(loss)

init = tf.global_variables_initializer()
sess.run(init)
losses = []
for i in range(3000):
    xs = [random.random() * 10 for j in range(max_len)]
    yy = sum(xs)
    # TODO batch_size, max_timeに対応する
    xs = [ [ [xx] for xx in xs] ] # shape 1, 3, 1
    sess.run(train_step, feed_dict={x: xs, y: yy})
    if i % 100 == 0:
        losses.append(sess.run(loss, feed_dict={x: xs, y: yy}))

print('vars : ', sess.run(rnn_cell.variables[0])) # RNNのウェイトを表示してみる
print('losses : ', losses)

動かしてみた結果がこちらです

vars :  [[ 0.94803673]
 [ 1.00511789]]
losses :  [189.65527, 120.48457, 402.87241, 0.10081632, 0.23049662, 0.54468751, 0.041665234, 0.57337528, 0.0074442979, 0.010118874, 0.097668171, 0.047499236, 0.22022037, 0.11357728, 0.14063072, 0.081412017, 0.15039197, 0.30661905, 0.010041318, 0.30713466, 0.2246805, 0.12985943, 0.013962295, 0.0031880976, 0.0033751372, 0.35504347, 0.043138403, 0.034578215, 0.17706399, 0.043236308]


一応想定した通り、variablesは(1, 1)あたりになってlossもなんとなく減っているみたいです

tensorflow で rnn を動かしてみる

tensorflow の rnn のチュートリアルはちょっと複雑で何をやってるのかパッとはわからないので、簡単なやつを作って動かしてみたい

そもそもRNNとは?

出力をまた入力に使うらしい。よくこんな図を見るけど具体的に何が起きているのか?

深層学習による自然言語処理 という本だと、

ということなので、1層で入力も出力も2個のときは、下図っぽい感じになるはず。

任意の長さの入力 (今回は入力素子が2個なので長さ4なら [ [3,2], [4,4], [1,0], [9,9] ] みたいな感じ) について、
最後の入力(上の例では [9,9])が渡されたときの出力(にsoftmaxとかかけたもの)で誤差関数の値を計算して、それを最小化するようにWを調整していくことで学習していく。
(必要なら各入力に対する出力を保存しておいてそれらで誤差関数を計算してもいいみたい)

入力の素子数が1つで活性化関数がreluとかなら、Wを全部1にしてbを全部0にすれば任意の長さの正の数の和が計算できそうなので、それを実装してみようと思う。

実装してみる


とりあえず、セルというものが必要らしいのでこれを作成する。
今回は1層だけだけどL層に重ねたりするときは、各層でWとかが存在するので、それぞれの層をひとまとめで表すものがセルなんだと思う。
今回は BasicRNNCell を利用する。

In [1]: import tensorflow as tf

In [2]: sess = tf.Session()

In [3]: size = 1

In [4]: rnn_cell = tf.nn.rnn_cell.BasicRNNCell(num_units=size, activation=tf.nn.relu)

BasicRNNCell は上で図示した感じの最も単純なネットワークのセル。
出力の素子数(num_units)と、利用する活性化関数(activation)を指定できる。

dynamic_rnn を使うとこれより先の処理を自分で書かなくてもよくなるっぽいけど、何が起こっているのか知りたいのでまずはdynamic_rnnを使わずに実装してみる。

各層の出力を入力として使うんだけど、一番最初の入力を渡すときは各層の出力(初期状態)は無いので何らかの値を指定しないと計算ができない。

セルの設定ごとに必要な初期状態のデータの形は変わるけどセル自体に初期状態のデータを出力する機能があるので、これを利用する

In [5]: n_batch = 1

In [6]: initial_state = rnn_cell.zero_state(n_batch, tf.float32)

In [7]: type(initial_state)
Out[7]: tensorflow.python.framework.ops.Tensor


ここまで来ると、任意の入力に対して出力を計算できるようになる

In [32]: x = tf.placeholder(tf.float32, shape=[None, n_batch, size])

In [47]: def inference(x, max_len):
    ...:     state = initial_state
    ...:     for i in range(max_len):
    ...:         (output, state) = rnn_cell(x[i], state)
    ...:     return tf.squeeze(output)
    ...: 

ほんとはxの長さでループを回したいんだけど上手いやり方がわからなかったので、とりあえず長さ固定でやることにする...

次に、誤差の計算をする

In [82]: max_len = 3

In [83]: output = inference(x, max_len)

In [84]: y = tf.placeholder(tf.float32, shape=[])    

In [85]: loss = tf.reduce_mean(tf.square(y - output))

誤差関数を最小化するための、optimizerを作る

In [86]: optimizer = tf.train.GradientDescentOptimizer(0.01)

In [88]: train_step = optimizer.minimize(loss)
In [89]: xs = [ [[[1]],[[2]],[[3]]],
    ...:        [[[2]],[[2]],[[2]]],
    ...:        [[[5]],[[4]],[[3]]],
    ...:        [[[7]],[[7]],[[7]]],
    ...:        [[[9]],[[8]],[[7]]] ]
    ...:        

In [95]: ys = [6, 6, 12, 21, 24]

In [96]: init = tf.global_variables_initializer()

In [97]: sess.run(init)

In [106]: for i in range(len(ys)):
     ...:     sess.run(train_step, feed_dict={x: xs[i], y: ys[i]})
     ...:     


やったー 学習させることに成功しました。

一応結果を確認してみます。

In [111]: print(sess.run(rnn_cell.variables[0])) # RNNのウェイトを表示してみる
[[-4.94734144]
 [-8.36993599]]

In [112]: loss.eval(session=sess, feed_dict={x:[[[1]],[[1]],[[1]]], y:3})
Out[112]: 9.0

学習データが大分少ないので全然誤差がでかいですが、とりあえず動かすことができたのでここまで

tensorflowの初歩の初歩

tensorのshape/dimension

一般的には m行n列の行列は m×n行列 と表記すると思うけど

m = tf.Variable([2,3])

とかしたときは2行3列なのか??とかちゃんとわかってないので確認したい

constantで確認する

In [12]: c1 = tf.constant([[1,2,3], [2,3,4]])

In [13]: c2 = tf.constant([[2,2], [3,3], [4,4]])

In [14]: sess.run(tf.matmul(c1, c2))
Out[14]: 
array([[20, 20],
       [29, 29]], dtype=int32)

In [15]: sess.run(tf.matmul(c2, c1))
Out[15]: 
array([[ 6, 10, 14],
       [ 9, 15, 21],
       [12, 20, 28]], dtype=int32)

In [16]: c1.shape
Out[16]: TensorShape([Dimension(2), Dimension(3)])

In [17]: c2.shape
Out[17]: TensorShape([Dimension(3), Dimension(2)])

ということで、constantでは shape(2, 3) は 2行3列 の行列を表すっぽい

では、縦ベクトル、横ベクトルはどうか?

In [18]: v1 = tf.constant([1,2,3])

In [19]: v2 = tf.constant([[2],[2],[2]])

In [21]: sess.run(tf.matmul(v1, v2))

...(略)
~/dev/tf-train/tf-env/lib/python3.6/site-packages/tensorflow/python/framework/common_shapes.py in _call_cpp_shape_fn_impl(op, input_tensors_needed, input_tensors_as_shapes_needed, require_shape_fn)
    689       missing_shape_fn = True
    690     else:
--> 691       raise ValueError(err.message)
    692 
    693   if missing_shape_fn:

ValueError: Shape must be rank 2 but is rank 1 for 'MatMul_2' (op: 'MatMul') with input shapes: [3], [3,1].

... rank が 2じゃなきゃいけないらしい

In [23]: v1.shape
Out[23]: TensorShape([Dimension(3)])

In [24]: v2.shape
Out[24]: TensorShape([Dimension(3), Dimension(1)])

https://www.tensorflow.org/programmers_guide/tensors

rank は 0がscalar, 1がvector, 2がmatrix らしい

逆に、縦ベクトルも横ベクトルも[1,2,3]みたいに書くべきなのか?

In [25]: v1 = tf.constant([1,2,3])

In [26]: v2 = tf.constant([2,2,2])

In [27]: sess.run(tf.matmul(v1, v2))
...(略)

~/dev/tf-train/tf-env/lib/python3.6/site-packages/tensorflow/python/framework/common_shapes.py in _call_cpp_shape_fn_impl(op, input_tensors_needed, input_tensors_as_shapes_needed, require_shape_fn)
    689       missing_shape_fn = True
    690     else:
--> 691       raise ValueError(err.message)
    692 
    693   if missing_shape_fn:

ValueError: Shape must be rank 2 but is rank 1 for 'MatMul_6' (op: 'MatMul') with input shapes: [3], [3].

やっぱりだめ 内積を計算したければ、ベクトルであっても1×n と n×1 の行列で表さなければならないみたい

In [31]: v1 = tf.constant([[1,2,3]])

In [32]: v2 = tf.constant([[2],[2],[2]])

In [33]: sess.run(tf.matmul(v1, v2))
Out[33]: array([[12]], dtype=int32)

In [34]: v1.shape
Out[34]: TensorShape([Dimension(1), Dimension(3)])

In [35]: v2.shape
Out[35]: TensorShape([Dimension(3), Dimension(1)])
shape part2

触りだしたらやっぱり理解があやふやだったので、再確認

shape [1,2,3] と shape [3,2,1] はどう違うのか?

左からi番目は外側からi番目の[]に入ってる要素の数、みたいに考えれば良さそう

In [12]: tf.constant([  [ [1,1,1], [2,2,2] ] ])
Out[12]: <tf.Tensor 'Const_4:0' shape=(1, 2, 3) dtype=int32>

shape [1, ...] なので 一番外側のに入っている要素は1つ

-> [ [...] ]

shape [1, 2, ...] なので 次のに入っている要素は2つ

-> [ [ [...], [...] ] ]

shape [1, 2, 3] なので 次の[]に入っている要素は3つ

-> [ [ [1,1,1], [2,2,2] ] ]

みたいな

逆に shape [3,2,1] なら

[ [...], [...], [...] ]

  • > [ [ [...], [...] ], [ [...], [...] ], [ [...], [...] ] ]
  • > [ [ [1], [2] ], [ [5], [6] ], [ [9], [0] ] ]

みたいな


あと c[1, :, 1] みたいな ':' をつかった操作もあんまり自信がないので確認

In [26]: c1 = tf.constant([[ [1,3,5], [2,4,6] ]])

In [27]: c2 = tf.constant([ [[1], [2]], [[5], [6]], [[9], [0]] ])

c1[0, :, 1] だと [ [3], [4] ]

c2[:, 1, :] だと [ [2], [6], [0] ]

c2[:, 1, 0] だと [2, 6, 0]

となるみたい

In [28]: sess.run(c1[0,:,1])
Out[28]: array([3, 4], dtype=int32)

In [29]: sess.run(c2[:,1,:])
Out[29]: 
array([[2],
       [6],
       [0]], dtype=int32)

In [30]: sess.run(c2[:,1,0])
Out[30]: array([2, 6, 0], dtype=int32)
scope

サンプルとか見ると

with tf.variable_scope("conv1"):
    ....

とかあるけどこれは何???

https://www.tensorflow.org/programmers_guide/variables

を読むと、同じ名前でget_variableを複数回呼ぶと変数を再利用するのか新規に作るのか判別できないけど、variable_scopeで区切っておけば別のvariable_scope内の変数は再利用しない、みたいなことらしい

In [37]: v1 = tf.get_variable('the_var', [2,3])

In [38]: v2 = tf.get_variable('the_var', [2,3])
... 略
ValueError: Variable the_var already exists, disallowed. Did you mean to set reuse=True or reuse=tf.AUTO_REUSE in VarScope? Originally defined at:

  File "<ipython-input-37-ce1950cb36a3>", line 1, in <module>
    v1 = tf.get_variable('the_var', [2,3])
  File "/home/shuhei/dev/tf-train/tf-env/lib/python3.6/site-packages/IPython/core/interactiveshell.py", line 2910, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "/home/shuhei/dev/tf-train/tf-env/lib/python3.6/site-packages/IPython/core/interactiveshell.py", line 2850, in run_ast_nodes
    if self.run_code(code, result):

やはり同名の変数を get_value しようとすると "Variable the_var already exists,"のエラーが起こるらしい
(reuse=Trueとかすれば再利用できるらしい)

これを、variable_scopeで囲っておくと別のスコープで定義された変数は無視して新しく作ってくれるらしい

In [39]: with tf.variable_scope('scope1'):
    ...:     v1 = tf.get_variable('scoped_var', [1,2])
    ...:     

In [40]: with tf.variable_scope('scope2'):
    ...:     v2 = tf.get_variable('scoped_var', [1,2])
    ...:     

In [41]: v1.name
Out[41]: 'scope1/scoped_var:0'

In [42]: v2.name
Out[42]: 'scope2/scoped_var:0'

面白いバラエティ番組に共通しているスタッフが作っている番組もきっと面白いんじゃないかと思って調べた

お笑い番組がすごく好きで昔からよく見ていたのですが、最近、"タレント☆名鑑も水曜日のダウンタウン藤井健太郎という人がつくっているのか!"、とか、"ゴットタンでもキングちゃんでも佐久間Pが出てきてるな〜"、とか思うことがあったので、"出演者よりも、作ってる人に着目したほうが好みの番組が探せるのでは?"と思い立って調べてみました。

僕が好きな番組は以下。


水曜日のダウンタウン
ゴッドタン
くりぃむナンチャラ
そんなバカなマン
さまぁ〜ず
NEO決戦バラエティ キングちゃん
バナナ炎
あらびき団
クイズ☆タレント名鑑
中井正広のブラックバラエティ
働くおっさん劇場
野性爆弾のザ・ワールド チャネリング


誰かが(特に設楽が)指示を出して何かやらせる系(そんなバカなマンのパシフィック・ヒムとか、神さまぁ〜ずのインスタント女王様決定戦とか、バナナ炎の悪者オーディションとか、キングちゃんのエキストラプロデュース王とか)がすごく好きhです。

上記の番組の中の複数の番組の制作に関わっている人というのは僕が好きそうな番組を作ってる人なのだろうから、その人が作っている他の番組を探していけば適当に探すより好きな番組に辿り着きやすいはず!、ということで、まず"上記の番組の中の複数の番組の制作に関わっている人"を調べてみました。

上記の番組のスタッフ一覧をWikipediaから持ってきて、雑なプログラムで重複している人の一覧を出してみました。コードは末尾に。

雑なので会社名とかも入ってしまっていますが、それはそれで"この会社が関わっている番組は面白い"みたいな見方ができるかもとおもってそのままにしています。


出力した結果は以下です。

スウィッシュジャパン ['水曜日のダウンタウン:ロケ技術', 'くりぃむナンチャラ:協力', 'NEO決戦バラエティ キングちゃん:技術協力', 'バナナ炎:協力', 'あらびき団:技術協力', 'クイズ☆タレント名鑑:ロケ技術']
大井洋一 ['水曜日のダウンタウン:構成', '神さまぁ〜ず:構成', 'NEO決戦バラエティ キングちゃん:構成', 'クイズ☆タレント名鑑:構成', '働くおっさん劇場:構成']
興津豪乃 ['水曜日のダウンタウン:構成', 'バナナ炎:構成', 'あらびき団:構成', 'クイズ☆タレント名鑑:構成']
成瀬正人 ['水曜日のダウンタウン:構成', 'ゴッドタン:構成', '神さまぁ〜ず:構成']
大西右人 ['水曜日のダウンタウン:構成', 'ゴッドタン:構成', 'そんなバカなマン:構成']
石川良則 ['水曜日のダウンタウン:音効', 'あらびき団:音効', 'クイズ☆タレント名鑑:音響効果']
小山陽介 ['水曜日のダウンタウン:宣伝', 'あらびき団:PR', 'クイズ☆タレント名鑑:宣伝']
水口健司 ['水曜日のダウンタウン:ディレクター', 'そんなバカなマン:ディレクター', 'クイズ☆タレント名鑑:ディレクター']
吉本興業 ['水曜日のダウンタウン:制作協力', 'あらびき団:制作協力', '働くおっさん劇場:制作']
TBS ['水曜日のダウンタウン:製作著作', '神さまぁ〜ず:製作', 'あらびき団:製作']
渡辺真也 ['水曜日のダウンタウン:構成', 'くりぃむナンチャラ:構成', 'クイズ☆タレント名鑑:構成']
オークラ ['ゴッドタン:構成', 'そんなバカなマン:構成', 'バナナ炎:構成']
永井ふわふわ ['ゴッドタン:構成', 'NEO決戦バラエティ キングちゃん:構成', 'バナナ炎:構成']
斉藤崇 ['ゴッドタン:ディレクター', 'そんなバカなマン:ディレクター', 'NEO決戦バラエティ キングちゃん:演出']
塩谷泰孝 ['ゴッドタン:ディレクター', 'そんなバカなマン:総合演出', '神さまぁ〜ず:ディレクター']
麻布プラザ ['そんなバカなマン:編集,MA', 'NEO決戦バラエティ キングちゃん:技術協力', '中井正広のブラックバラエティ:技術協力']
五十嵐陽 ['NEO決戦バラエティ キングちゃん:カメラ', 'バナナ炎:CAM', 'あらびき団:CAM']
服部潤 ['水曜日のダウンタウン:ナレーション', 'ゴッドタン:ナレーション']
高須光聖 ['水曜日のダウンタウン:構成', '働くおっさん劇場:構成']
矢野了平 ['水曜日のダウンタウン:構成', 'クイズ☆タレント名鑑:構成']
坂口司 ['水曜日のダウンタウン:TD', 'クイズ☆タレント名鑑:TD']
渋谷康治 ['水曜日のダウンタウン:照明', 'クイズ☆タレント名鑑:照明']
関美幸 ['水曜日のダウンタウン:編集', 'クイズ☆タレント名鑑:編集']
伊藤佳加 ['水曜日のダウンタウン:TK', 'クイズ☆タレント名鑑:TK']
新貝元章 ['水曜日のダウンタウン:AP', 'クイズ☆タレント名鑑:キャスティングP']
竹井晶子 ['水曜日のダウンタウン:AP', 'クイズ☆タレント名鑑:AP']
田中良憲 ['水曜日のダウンタウン:ディレクター', 'クイズ☆タレント名鑑:ディレクター']
佐々木卓也 ['水曜日のダウンタウン:ディレクター', 'クイズ☆タレント名鑑:ディレクター']
池田哲也 ['水曜日のダウンタウン:ディレクター', 'NEO決戦バラエティ キングちゃん:ディレクター']
藤井健太郎 ['水曜日のダウンタウン:演出', 'クイズ☆タレント名鑑:演出,プロデューサー']
山口智広 ['水曜日のダウンタウン:美術プロデューサー', 'クイズ☆タレント名鑑:美術プロデューサー']
齊藤傑 ['水曜日のダウンタウン:デザイン', 'クイズ☆タレント名鑑:美術デザイン']
宮本稔久 ['水曜日のダウンタウン:制作プロデューサー', 'あらびき団:プロデューサー']
森俊平 ['水曜日のダウンタウン:制作進行', 'NEO決戦バラエティ キングちゃん:ディレクター']
高田脩 ['水曜日のダウンタウン:ディレクター', 'クイズ☆タレント名鑑:ディレクター']
三枝浩史 ['水曜日のダウンタウン:ディレクター', 'NEO決戦バラエティ キングちゃん:ディレクター']
相澤昇 ['ゴッドタン:構成', 'NEO決戦バラエティ キングちゃん:構成']
小田切暁 ['ゴッドタン:音響効果', 'そんなバカなマン:音響効果']
魚田英孝 ['ゴッドタン:番宣', 'NEO決戦バラエティ キングちゃん:番宣']
テクノマックス ['ゴッドタン:技術協力', 'あらびき団:技術協力']
テレビ東京アート ['ゴッドタン:美術,照明協力', 'あらびき団:技術協力']
美濃部遥香 ['ゴッドタン:AP', 'そんなバカなマン:AP']
双津大地郎 ['ゴッドタン:ディレクター', 'そんなバカなマン:ディレクター']
高井翔太朗 ['ゴッドタン:ディレクター', 'そんなバカなマン:ディレクター']
廣田彰大 ['ゴッドタン:ディレクター', 'そんなバカなマン:ディレクター']
佐久間宣行 ['ゴッドタン:プロデューサー,演出', 'NEO決戦バラエティ キングちゃん:プロデューサー']
シオプロ ['ゴッドタン:制作協力', 'そんなバカなマン:制作協力']
テレビ東京 ['ゴッドタン:製作著作', 'NEO決戦バラエティ キングちゃん:製作著作']
北本かつら ['ゴッドタン:構成', 'くりぃむナンチャラ:構成']
山田かつら ['ゴッドタン:メイク', 'そんなバカなマン:メイク']
小室良太 ['ゴッドタン:演出補', 'そんなバカなマン:プロデューサー']
IMAGICA ['くりぃむナンチャラ:協力', '働くおっさん劇場:技術協力']
加用裕紀 ['そんなバカなマン:ディレクター', 'バナナ炎:ディレクター']
フジテレビ ['そんなバカなマン:制作著作', '働くおっさん劇場:制作']
松井光太郎 ['そんなバカなマン:CAM', '神さまぁ〜ず:カメラ']
安藤雄郎 ['そんなバカなマン:LD', '神さまぁ〜ず:照明']
橋本竜也 ['NEO決戦バラエティ キングちゃん:EED', '中井正広のブラックバラエティ:編集']
柳沼修 ['バナナ炎:VE', 'あらびき団:VE']
蓮田貴志 ['あらびき団:編集', 'あらびき団:VTR編集']
鈴木建介 ['あらびき団:編集', 'あらびき団:編集']

2番組以上に関わっている人は60人いました。
気になった人たちを少し調べて見ました。

スウィッシュジャパン

https://ja.wikipedia.org/wiki/%E3%82%B9%E3%82%A6%E3%82%A3%E3%83%83%E3%82%B7%E3%83%A5%E3%83%BB%E3%82%B8%E3%83%A3%E3%83%91%E3%83%B3

'水曜日のダウンタウン:ロケ技術',
'くりぃむナンチャラ:協力',
'NEO決戦バラエティ キングちゃん:技術協力',
'バナナ炎:協力',
'あらびき団:技術協力',
'クイズ☆タレント名鑑:ロケ技術'

12番組中半分の6番組に関わっていた制作会社。Wikipediaの記事をみると、めちゃくちゃいろんな番組に関わっているようなのでこの結果にも納得です。
キングちゃんに東野幸治が出たときに"あらびき団のカメラマンだった人じゃないですか!"みたいな事を言っていたけどもしかしたらこの会社の人なのかも?と思いました。制作会社が何をする会社なのかわかってないので、カメラマンとか全然関係なかったらごめんなさい。

大井洋一

https://ja.wikipedia.org/wiki/%E5%A4%A7%E4%BA%95%E6%B4%8B%E4%B8%80

'水曜日のダウンタウン:構成',
'神さまぁ〜ず:構成',
'NEO決戦バラエティ キングちゃん:構成',
'クイズ☆タレント名鑑:構成',
'働くおっさん劇場:構成'

個人では最多の5番組に関わっていた放送作家の方。
"コレってアリですか?"という番組はみたことがなかったのでDVDを探してみようと思います。

興津豪乃

https://ja.wikipedia.org/wiki/%E8%88%88%E6%B4%A5%E8%B1%AA%E4%B9%83

'水曜日のダウンタウン:構成',
'バナナ炎:構成',
'あらびき団:構成',
'クイズ☆タレント名鑑:構成'

4番組は全体で3番目、個人では2番目。
"有吉弘行のダレトク!?"とか"金曜★ロンドンハーツ"とか、調査しなかったけど好きな番組に関わっている方のようです。
"チェンジ3"という番組は今もやっているようなので見てみます。

水口健司

https://twitter.com/mizukenji

'水曜日のダウンタウン:ディレクター',
'そんなバカなマン:ディレクター',
'クイズ☆タレント名鑑:ディレクター'

上位の方は構成の方が多かったのですが、こちらのかたはディレクターのようです。
"とんぱちオードリー", "万年B組ヒムケン先生", "芸人キャノンボール"など、気になるタイトルの番組にも関わっているようなので、これらも見てみようと思います。
次の塩谷泰孝という方が社長をやっているシオプロという会社の方のようです。


塩谷泰孝

https://ja.wikipedia.org/wiki/%E3%82%B7%E3%82%AA%E3%83%97%E3%83%AD

'ゴッドタン:ディレクター',
'そんなバカなマン:総合演出',
'神さまぁ〜ず:ディレクター'

"インスタンス女王様とパシフィックヒムはやっぱり同じ人が作っていたんだ!"と思いました(実際は違うのかもしれません)。
"クレイジージャーニー"ってみたことなかったですが見てみようと思います。
あと、AbemaTVで"フジモンのやりたい10のこと"という番組もやっているようなのでそちらも気になります。

感想

いくつか気になる番組がみつかったので良かったです。
他にも気になった人がいたのですが、他にどんな番組に関わっているかの情報が見つけられなかった人がいたので残念でした。
水曜日のダウンタウンとタレント名鑑とか、ゴッドタンとそんなバカなマンとか、結構重複している人がおおかったので、やっぱりチームで作ってる感じなんだろうなと思いました。

コード
# coding: utf-8

import re

staffs = {'野性爆弾のザ・ワールド チャネリング': '''脚本:佐藤篤志
音楽:石崎勝巳
撮影:今井裕二
証明:大町昌路
録音:古茂田耕吉
美術:山崎輝
装飾:佐藤希、阿久津桂
持道具:中村麻理子
衣装:村島恵子、山下由
ヘアメイク:高橋亮
特殊メイク:百武朋
助監督:後藤ヨシチカ
音響効果・編集:渕野由美
整音・MA:藤本淳
撮影助手:吉田太一
照明助手:二枝史子
特殊メイク助手:並河学
制作主任:大石淳也
制作応援:赤瀬一紀
演出部見習い:半沢和樹
スチール:大蔵俊介、橋本悠平
助監督:谷口仁則
AP:斎木綾乃
プロデューサー:大沼知朗、服巻泰三、上野遼平''',
'水曜日のダウンタウン': '''ナレーション:服部潤
構成:高須光聖、興津豪乃、大井洋一、矢野了平、成瀬正人、飯塚大悟、大西右人
TM:小澤義春
TD:廣田雅之、坂口司
CAM:中野真悟
VE:高橋康弘
音声:中村全希
照明:渋谷康治
ロケ技術:SWISH JAPAN
音効:石川良則
美術プロデューサー:中西忠司
デザイン:松田エリザベス玲子
美術制作:桂誉和
装置:坂本進
電飾:荒谷奏子
装置操作:牧ヶ谷純二
アクリル装飾:井上惠介
小道具:田村健治
持道具:小松絵里子
編集:関美幸、高橋雄人
MA:市川徹
衣裳:岩崎孝典
スタイリスト:高堂のりこ、北田あつ子
メイク:Office MAKISE、岡葵
機材協力:東京オフラインセンター
協力:BACK-UP MEDIA
曲:PUNPEE
CG:ODD JOB
TK:伊藤佳加
リサーチ:亀田貴誠、ジーワン
編成:高橋智大[注 16]
宣伝:小山陽介
デスク:松崎由美
AP:新貝元章、菊池絢子、竹井晶子、宮里良子、近藤陽子、真壁正彦
ディレクター:横井雄一郎、田中良憲、町田有史 / 水口健司、佐々木卓也、久野公嗣、高畑忠司、池田哲也、村中良輔、角田瞬、田村裕之、小林悦子
制作プロデューサー:田井中皓介(以前はAP)、今瀧陽介
監修:柳岡秀一
MP(マネージメントプロデューサー):渡辺英樹[注 17]
演出:藤井健太郎(以前はプロデューサー兼務)
プロデューサー:坂本義幸(以前は担当プロデューサー)
制作協力:吉本興業
製作著作:TBS
構成:渡辺真也[注 18]
TM:山下直、丹野至之
音声:稲津貴之
音効:丹羽さやか、古賀香澄
美術プロデューサー:山口智広
デザイン:齊藤傑
美術制作:川崎光紘
アクリル装飾:相澤香織、井上大華
持道具:寺澤麻由美
MA:新田領
メイク:梅原恵里
曲:パソピー(水曜日のダウソタウソ)
編成:田口健介、中井芳彦、辻有一
宣伝:奥住達也
制作プロデューサー:宮本稔久、谷垣和歌子
制作進行:森俊平
AP:織田直也、花田真志、古川亜希子
ディレクター:高柳健人、須藤駿、高田脩、日野智文、杉本真宣、三枝浩史
制作プロデューサー:山田貢
MP(マネージメントプロデューサー):中川通成、中鉢功
プロデューサー:福田健太郎(以前は編成)
EP:安田淳''',
'ゴッドタン': '''ナレーション:服部潤[注 27]
構成:オークラ、相澤昇、くらなり、成瀬正人、永井ふわふわ[注 28]、大西右人[注 29]
技術:丸山真平(テレビ東京、以前はカメラ)
映像:入江俊之(テレビ東京)
カメラ:風間誠
照明:曽我秀樹
音声:永久保仁志
デザイン:金森明日香(以前は美術進行)
美術進行:仙田拓也
大道具:工藤義昭
小道具:山下正美
メイク:蔵本優花
EED:落合勇(CC Factory〈旧TDKコア〉)
MA:長瀬貴広
音響効果:小田切暁(278→NAP)
タイトル:上田大樹(&FICTION!)
番宣:魚田英孝(テレビ東京、以前はディレクター、一時離脱→復帰)
技術協力:テクノマックス
美術・照明協力:テレビ東京アート
演出補:岡千尋
AP:美濃部遥香(以前は演出補)
ディレクター:田村育 / 今村光宏、斉藤崇、双津大地郎、塩谷泰孝、高井翔太朗(高井→以前は演出補、一時離脱→復帰)、廣田彰大、土屋佳弘(土屋→以前は演出補、一時離脱)(以上シオプロ)
プロデューサー:露木寛子(一時離脱→復帰)(テレビ東京)
プロデューサー / 演出:佐久間宣行(テレビ東京)
協力:ナカムラ綜美
制作協力:シオプロ(2010年10月6日 - )
製作著作:テレビ東京
タイトルコール:INCREDIBLE BEATBOX BAND
プロデューサー:伊藤隆行(初期)・五箇公貴( - 2007年7月18日)・石井成臣(3人共テレビ東京)/志岐誠(NAVI、 - 2010年9月29日)
アシスタントプロデューサー(AP):みうらさなえ( - 2009年5月13日)
構成:北本かつら / 堀田延( - 2010年9月29日)
技術:菊池裕介、野瀬一成(野瀬→以前はカメラ)、吉田健吾(テレビ東京)
映像:佐藤誠二、葛西雅弘、細井昭宏、宮本裕美子、北村宏一、佐久間元貴(テレビ東京)
カメラ:近藤剛史(テレビ東京)
照明:小林瑞雪、宮尾淳一
音声:大津幹弘、斉藤孝行
美術:小越敏彦
小道具:植田幸奈
メイク:山田かつら
ビジュアルフォーマット:松本哲也(CC Factory〈旧TDKコア〉)
EED:神保和則
音響効果:林正貴(278)
番宣:保科啓・小林教子・大塚淳・野上次郎・井上健二・岡仁・大城博章(テレビ東京)
デスク:海野和可奈・露木彩乃(テレビ東京)
ディレクター:小石重蔵、姫野善行(姫野→以前は演出補)、桑原宏次・水野亮太・藤枝彰・田中晋也・板川侑右(テレビ東京)
演出補:篠原裕明(テレビ東京)、亀川匡、小室良太、秋山博明
制作協力:NAVI( - 2010年9月29日)''',
'くりぃむナンチャラ': '''ナレーション:佐藤賢治
構成:渡辺真也、町田裕章、北本かつら、樅野太紀
カメラ:門倉秀樹
音声:田原裕太
照明:吉岡駿
美術:井磧伸介
デザイン:山下高広
美術進行:山本和記
大道具:小宮山博章
ヘアメイク:川口かつら
CG:南治樹、真栄城樹
音効:加藤つよし
編集:小野坂智
MA:宝月健
編成:瀧川恵
宣伝:高橋夏子
TK:吉条雅美
デスク:相馬恵美
協力:テレビ朝日クリエイト、SWISH JAPAN、IMAGICA
AD:金山将世、渡辺直哉
ディレクター:藤本達也、宮本大輔、大野剛史、土井功輔、山本健矢
プロデューサー:小田隆一郎、三藤豊
ゼネラルプロデューサー:畔柳吉彦
制作著作:テレビ朝日
TM:大島秀一
デザイン:濱野恭平、飛田幸
美術進行:入江大介、廣澤陽子
大道具:後藤貴弘
ヘアメイク:小川和美
編集:久保田和樹
編成:高橋正輝、大沢解都
AD:田中晋平
AP:吉田奈央
ゼネラルプロデューサー:藤井智久''',
'そんなバカなマン': '''構成:酒井健作、オークラ、宮森亮(かわら)●
ナレーション:梶裕貴、内田彩
TP:小林錦司●
SW:竹内弘佳●
CAM:古俣智則●
VE:澤田将人
AUD:元山拓己(巳)●
照明:黒井宏行●
音響効果:小田切暁
TK:斉藤裕里
美術プロデューサー:三竹寛典
デザイン:鈴木賢太
美術進行:中村秀美●
大道具制作:山本和成(特番時→大道具操作)
アクリル装飾:相原加奈
メイク:山田かつら
CG:星野安規(Kitty)、三重の人●(kitty)
音楽:the zombies
技術協力:fmt
編集:早川徹哉、前島神奈(前島→以前は編集・MA、一時離脱→復帰)(共に●)
MA:河村大樹●
広報:片山正康●
デスク:市川亜季
Webデザイナー:星野倫美●
AD:佐々木博基、寺本文子(共に●)
AP:美濃部遥香
ディレクター:中西正太、水口健司、高井翔太朗(高井→●)/双津大地郎、斉藤崇、加用裕紀、廣田彰大
プロデューサー:小室良太(シオプロ)
チーフプロデューサー:飯村徹郎(フジテレビ)
総合演出:塩谷泰孝(シオプロ、特番時→演出)
制作協力:シオプロ
制作著作:フジテレビ
構成:大西賢一●、大西右人
TD:若林茂人
SW:浜島一雄
CAM:涌田尚孝、松井光太郎
AUD:絹山幸広
LD:安藤雄郎
美術進行:平山雄大
大道具制作:前田かなこ
メイク:岡田美喜子●
イラスト:大野そら
編集・MA:麻布プラザ、岡田秀夫、林仁美、松阪史高(岡田〜松阪→●)
スペシャルサンクス:野上翔、八代拓、東内マリ子、秋林優花
広報:清田美智子
Webマスター:中山直人●
Webディレクター:藁谷憲幸●
AD:宇田川雄大、備前慎悟、榎本萌菜、柴田千尋●、倉知瑠一●、岡田直美●、馬庭広明●、武藤勇次●
ディレクター:栗坪隆平
チーフプロデューサー:明松功''',
'神さまぁ〜ず': '''企画:大竹一樹 (2008年4月 - 9月)
ナレーション: 中村正 → チェン・チュー → 中村英香(DVDのナレーションも担当)
構成: 大井洋一、成瀬正人、中野恵介、如月聖也
カメラ: 松井光太郎
音声: 谷川宏輝
照明: 安藤雄郎
メイク: 福田祐子
音効: 村松聡・谷脇和正(佳夢音)
技術協力: 八峯テレビ、アンサーズ、FLT、東京タワースタジオ
AP: 高橋利一郎、増岡曲子
ディレクター: 塩谷泰孝、ちのうあい
演出: 水野達也
プロデューサー: 飯沼美佐子
製作: G-yama 、TBS''',
'NEO決戦バラエティ キングちゃん': '''ナレーション:朝倉崇
構成:相澤昇、川上テッペイ、大井洋一(大井→2017年4月10日-)、永井ふわふわ
カメラ:五十嵐陽
音声:織部佳和
美術:丹野ありさ(2017年4月10日-)
EED:森岡佑次、佐々木智司、曽根徹、小森佑輔、北浦美夫、増田功紀、森嶋亮、望月浩久、岩品博之、石上淳、坪野陽季、安田裕禎、山中健司、今坂勇介、藤河優、大場浩二、中島功二、篠崎孝徳、橋本竜也、曽根隼一
MA:長谷川真哉、大野健志、岡崎穣、中尾和博
音響効果:遠藤治朗
タイトル:前川陽介
番宣:魚田英孝(テレビ東京、一時離脱→復帰)
技術協力:スウィッシュ・ジャパン、麻布プラザ
美術協力:フジアール、.movs
演出補:渋谷優介、三浦奈々(三浦→2017年4月10日-)、小林孔治
AP:森友絵(2017年4月10日-)
ディレクター:三枝浩史、橋本詳吾、森俊平
演出:斉藤崇
制作プロデューサー:碓氷容子
プロデューサー:佐久間宣行(テレビ東京)
制作協力:HYBRID FACTORY
製作著作:テレビ東京
美術:内藤佳奈子、円城寺一平
音響効果:千本洋
編成:森本泰介(テレビ東京)
番宣:福井静(テレビ東京)
技術協力:デジタルサーカス
演出補:泉澤康智、上野直人、宮城さんご
ディレクター:池田哲也''',
'バナナ炎': '''総合演出:椎葉宏治
ナレーター:落合隼亮
構成:オークラ、寺田智和、興津豪乃、永井ふわふわ
TD:石毛雄己
CAM:五十嵐陽
VE:柳沼修
AUD:目野智子
PA:橋本淳志
美術プロデューサー:関口美千代
美術進行:佐藤政之
デザイン:ヨシマルシン
スタイリスト:渡辺光
ヘアメイク:ファーストステップ
編集:真野公宏
MA:杉山勉
音効:上口昭雄
AP:妹尾こずえ
協力:ソニー・ミュージックエンタテインメント、ホリプロコム、スウィッシュ・ジャパン、ミッククリエーション、シアターエンジニアリング、トゥミックス
ディレクター:鳥越一夫、好田康智、加用裕紀
プロデューサー:北詰由賀、相沢直、扇京子
エグゼクティブプロデューサー:宮原匡彦
企画:テレバイダー・エンタテインメント[注釈 11]
製作著作:バナナ炎パートナーズ''',
'あらびき団': '''総合演出:原田浩司
構成:中野俊成、松本真一、興津豪乃、遠藤敬、岸本浩二、森、柴田健太郎、今井太郎
CAM:五十嵐陽
AUD:渡辺拓
VE:柳沼修
照明:翁美希子
美術進行:佐藤研英
美術デザイン:松井夢壮、姉川たく(カニカピラ)、田中利明
ヘアメイク:TEES
スタイリスト:山岡かおり
編集:蓮田貴志、鈴木大知、鈴木建介
MA:中村裕子
音効:石川良則
CG:長澤剛史
PR:小山陽介
AD:尾崎まなみ、高橋尚史、伊藤竜太、山村勇介、佐藤国秀
ディレクター:相澤雄、齋藤慎一郎、大森千代美、岩津匡洋、一場孝夫
AP:中野加奈子(NET WEB)、森俊和(よしもとクリエイティブ・エージェンシー)
制作プロデューサー:村田聡子・中塚大悟(NET WEB)
プロデューサー:江間浩司(NET WEB)、宮本稔久(よしもとクリエイティブ・エージェンシー)
技術協力:スウィッシュ・ジャパン、テクノマックス、三雅、ザ・チューブ、テレビ東京アート、SPOT、VOXEL
制作協力:吉本興業
製作:NET WEB、TBS
総合演出:渡辺剛(NET WEB)
AD:石川千成、由茅奈保美、ナオミヤユガ(ケニア)(美女)、沖島新菜、濱田禮徳、田中雄大
ディレクター:川向涼子、本間和美、木村亮
AP:山下征志・土屋達彦・城下拓也・中原隆二・沖本翔子(よしもとクリエイティブ・エージェンシー)、八木愛子
編成:山田康裕
PR:國重希理佳
編集:鈴木建介
MA:伊藤慎吾
VTR編集:蓮田貴志''',
'クイズ☆タレント名鑑': '''ナレーション:銀河万丈
構成:興津豪乃、大井洋一、矢野了平、田中淳也、村上洋賢、梶谷直人/渡辺真也
TM:金澤健一
TD:坂口司
カメラ:中島文章
VE:青木孝憲
音声:渡邉学
照明:渋谷康治
ロケ技術:スウィッシュ・ジャパン
美術プロデューサー:山口智広
美術デザイン:齊藤傑
美術制作:五十川弘一
装置:森田正樹
操作:今野貴司
装飾:森田琴衣
メカシステム:庄子泰広
電飾:梅本孝
持道具:岩本美徳
衣裳:君和田悦子
ヘアメイク:市川温子、佐野優美子
スタイリスト:渡辺浩司
編集:遠藤毅、関美幸
MA:宮嶌宏道
音響効果:石川良則、沢井隆志
タイトルデザイン:草野剛
OPアニメ:シャシャミン&ケイト・アロー(ODDJOB)
CG:Rimo from mocrock&Dr.Ueno(ODDJOB、タイムライン)
TK:伊藤佳加
デスク:椿美貴子
編成:藤原麻知
宣伝:小山陽介
AP:竹井晶子/鈴木愛子
キャスティングP:新貝元章
ディレクター:有田武史、柳信也、水口健司、前島隆昭、佐々木卓也、高田脩、林博史/岡宗秀吾
プロデューサー:西川永哲
演出・プロデューサー:藤井健太郎
CP:合田隆信
制作:TBSテレビ
脚本協力:楠野一郎(GO!ピロミ殺人事件)
VE:宇都宮勝
音声:藤井勝彦
美術制作:小杉理紗
装飾:深山健太郎
電飾:安島美次
持道具:貞中照美
編成:平田さおり(パイロット版)
宣伝:嵯峨一孝
ディレクター:田中良憲(パイロット版)''',
'中井正広のブラックバラエティ': '''構成 : クリタヤスシ、はっしー橋本、とちぼり元
リサーチ : てれすこ、フォーミュレーション
TM : 石塚功
SW : 村松明
CAM : 村上和正
MIX : 今野健
音声 : 山田値久、亘美千子、藤岡絵里子
VE : 石野太一、矢田部昭、鈴木昭博、山口考志
照明 : 平田丈、森田恵太郎、山内圭
美術 : 三浦昭彦
デザイン : 道勧英樹
タイトル : 安居院一展
編集 : 橋本竜也、川口達也、名雪健太郎、望月恵太、村田充、平池優太、朝日豊
MA : 佐藤卓也、大田将一
音効 : 花岡英夫
TK : 恩田明子
デスク : 濱村吏加
広報 : 西室由香里(一時離脱していたが復帰)
美術・照明協力 : 日本テレビアート
技術協力 : NiTRO、ヌーベルバーグ、MIDGET、東京藤田工業、麻布プラザ
スタイリスト : 富岡祥寿
ヘアメイク : 山内勝博
AP : 内田佳与子
AD : 石橋浩二、遠藤隼人、柳川雄洋、小林裕樹、佐藤亮介、澤江智由喜、長富紗良、岡山眞也
ディレクター : 瀬戸口晃、深沢博信、二神新、坂仲久恵、武藤和也、馬杉光
演出 : 中谷聡、さとうしゅう
総合演出 : 村上和彦
プロデューサー : 小澤太郎/ 杉田文彦、磯和伸明、岡村光洋
チーフプロデューサー : 安岡喜郎
協力 : ジャニーズ事務所
制作協力 : いまじん、えすと、ビショップ
製作著作 : 日本テレビ
TM : 牛山雅博、勝見明久、伊東俊哉
CAM : 中川昭生
照明 : 中瀬有紀、小川勉
キャラクターデザイン : 山本峰規子
デスク : 大黒紫
広報 : 神山喜久子
美術 : 林健一
リサーチ : FULLTIME.CO.LTD.
調査 : 松崎郁子
スタイリスト : 伊藤紫
ヘアメイク : 諏訪部留美
AP : 糸井聖一、青木かおる
AD : 先崎真耶
ディレクター : 篠幸生、久木野大、岩佐学、林芳昌、齋藤雅美、石田直人
プロデューサー : 環真吾、村手武治、行方久司
チーフプロデューサー : 政橋雅人、染井将吾、鈴江秀樹''',
'働くおっさん劇場': '''企画:松本人志
構成:高須光聖、渡辺鐘、大井洋一
美術制作:大坊雄二
美術進行:林勇
カメラ:遠山康之
VE:齋藤雄一
音声:杉山直樹
編集:太田友康
MA:円城寺暁
音響効果:高田智彰
TK:菅原洋子
プロデューサー:江本薫(フジテレビ)、高畑正和(吉本興業)
チーフプロデューサー:佐々木将(フジテレビ)
演出・プロデュース:伊藤征章(フジテレビ)
技術協力:ニユーテレス、IMAGICA
制作:フジテレビ、吉本興業'''
}

def split(line):
    line = line.replace('スウィッシュ・ジャパン', 'スウィッシュジャパン') \
               .replace('SWISH JAPAN', 'スウィッシュジャパン') \
               .replace('チェン・チュー', 'チェンチュー') \
               .replace(':', ':') \
               .replace('、', ',') \
               .replace('・', ',') \
               .replace('→', ',') \
               .replace('/', ',') \
               .replace('/', ',') \
               .replace('(', '(') \
               .replace(')', ')') \
               .replace('●', '') \
               .replace(' ', '')
    line = re.sub(r'\(.+?\)', '', line)
    line = re.sub(r'\[.+?\]', '', line)
    role = line.split(':')[0]
    names = line.split(':')[1].split(',')
    return names, role

result = dict()

for title in staffs:
    lines = staffs[title].split('\n')
    for line in lines:
        names, role = split(line)
        for name in names:
            if name not in result:
                result[name] = []
            if title not in result[name]:
                result[name].append(title + ':' + role)


for (name, titles) in sorted(result.items(), key=lambda x: -len(x[1])):
    if (len(titles) > 1):
        print(name, titles)