質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.50%

  • Python

    8008questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Pythonで重み付き多数決について

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 698

gymgym

score 67

7個のリストから重み係数つきの多数決を行って、その結果から1個のリストを作成したいと考えています。

a = [ 1  0  2  2  2  1  1  0  2  4  3  3  5  3  5  4  6  5  6  7  6  8  7  8  6
  8  6 11 11  9 10 11 11 11  9 11]
b = [ 1  0  2  2  2  1  1  0  2  5  4  5  5  5  4  4  4  4  6  4  4  8  4  8  7
  8  6  9 11  9 11  9 11 10  9 11]
c = [ 1  0  2  2  2  1  1  0  2  5  4  5  3  4  4  4  5  5  6  7  6  8  7  8  6
  8  6  9  9  9 10  9 11 10  9 11]
d = [ 1  0  2  2  2  1  1  0  2  5  5  5  3  3  5  5  5  3  6  7  6  8  6  8  6
  8  6  9  9 10 10  9 10  9  9 11]
e = [ 0  2  2  0  1  0  0  2  0  3  5  3  4  4  3  4  3  4  8  8  6  6  7  6  8
  6  8  9  9  9 10 10 10 10  9 10]
f = [ 1  0  2  2  2  1  1  2  2  5  5  5  3  3  5  5  5  5  6  7  6  8  7  8  6
  8  6  9  9 10 10  9 11 10  9 11]
g = [ 1  1  2  2  2  1  1  2  2  4  5  5  4  4  5  3  5  5  6  4  4  8  7  8  6
  8  6  9 11  9 10  9 11 10  9 11]

aの重み係数: w1 = 0.417
bの重み係数: w2 = 0.278
cの重み係数: w3 = 0.444
dの重み係数: w4 = 0.333
eの重み係数: w5 = 0.333
fの重み係数: w6 = 0.361
gの重み係数: w7 = 0.333

それぞれのリストの1〜リストの長さ番目までの要素でそれぞれ重み付き係数を利用して多数決を行いリストを作成することが目的です。

label_list = [a,b,c,d,e,f,g]
weight = [w1, w2, w3, w4, w5, w6, w7]
labels = []
N = len(label_list[0])
for n in range(N):
    for i, w in zip(label_list, weight):
        a, gu, ty, pa, = [], [], [], []
        if(i[n] % 3 == 0):
            gu.append(w)
        elif(i[n] % 3 == 1):
            ty.append(w)
        elif(i[n] % 3 == 2):
            pa.append(w)

    x = [sum(gu), sum(ty), sum(pa)]
    x.sort()
    if(x[0] == sum(gu)):


リストの要素の数字によって、3つのリストを作成して重み係数をラベルによって分けてリストの合計をそれぞれ算出して一番大きい数のリストに応じて、ラベルをつけていこうと考えたのですがコードで表現できなくて困っています。

以上の文章では、意図がわかりづらいと思います。うまく説明できなくてすみません。

もっとうまい方法がありましたら、参考にさせてもらいたいので教えていただきたいです。

よろしくお願い致します。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

7個のリストから重み係数つきの多数決を行って、その結果から1個のリストを作成したい

次のようにして実現できそうです。

def get_most_popular_topic(topics, num_of_topic, weights=None):
    if weights is None:
        weights = np.array([1] * topics.shape[0])

    topic_table = np.array([
        np.dot(weights.T, (topics==i).astype(int))
        for i in range(num_of_topic)
    ])
    print(topic_table)
    return np.argmax(topic_table, axis=0)


best_topics = get_most_popular_topic(
    np.vstack((a, b, c, d, e, f, g)), 12
    np.array(w)
)

考え方

簡単なデータで動作を確認してみましょう。

topics = np.array([
    [0, 0, 0, 0, 1, 1, 1, 1],  # w=1
    [0, 0, 1, 1, 0, 0, 1, 1],  # w=1
    [0, 1, 0, 1, 0, 1, 0, 1]   # w=2
])
weights = np.array([1, 1, 2])

まず、トピック0についてマスクを作ります。
numpyを用いればこの処理は至って簡単です。

>>> topics==0
array([[ True,  True,  True,  True, False, False, False, False],
       [ True,  True, False, False,  True,  True, False, False],
       [ True, False,  True, False,  True, False,  True, False]], dtype=bool)

このままでは使いにくいので、Trueを1に、Falseを0と解釈しなおします。

>>> (topics==0).astype(int)
array([[1, 1, 1, 1, 0, 0, 0, 0],
       [1, 1, 0, 0, 1, 1, 0, 0],
       [1, 0, 1, 0, 1, 0, 1, 0]])

重み付きの和が欲しいので、weightsを左からかけます。

>>> np.dot(weights.T, (topics==0).astype(int))
array([4, 2, 3, 1, 3, 1, 2, 0])

この出力は、『トピック0に関する重み』です。
実際に手で計算したときと同じ結果が得られます(当たり前ですが)。

それ以外の結果も連ねると、次のような結果になります。

[[4 2 3 1 3 1 2 0]   # トピック0の重み
 [0 2 1 3 1 3 2 4]]  # トピック1の重み

このような表を作れば、ただの最大値の選択に話題を置き換えることが出来ます。
『最大値がどの行にあるか』が重要なので、np.argmaxを使います。

>>> topic_table
array([[4, 2, 3, 1, 3, 1, 2, 0],
       [0, 2, 1, 3, 1, 3, 2, 4]])
>>> np.argmax(topic_table, axis=0)
array([0, 0, 0, 1, 0, 1, 0, 1], dtype=int64)

このようにして、『最も重い』トピックを選ぶことが出来ました。

なお、元のデータで試すと

a = [
     1,  0,  2,  2,  2,  1,  1,  0,  2,  4,  3,  3,
     5,  3,  5,  4,  6,  5,  6,  7,  6,  8,  7,  8,
     6,  8,  6, 11, 11,  9, 10, 11, 11, 11,  9, 11
]
b = [
     1,  0,  2,  2,  2,  1,  1,  0,  2,  5,  4,  5,
     5,  5,  4,  4,  4,  4,  6,  4,  4,  8,  4,  8,
     7,  8,  6,  9, 11,  9, 11,  9, 11, 10,  9, 11
]
c = [
     1,  0,  2,  2,  2,  1,  1,  0,  2,  5,  4,  5,
     3,  4,  4,  4,  5,  5,  6,  7,  6,  8,  7,  8,
     6,  8,  6,  9,  9,  9, 10,  9, 11, 10,  9, 11
]
d = [
     1,  0,  2,  2,  2,  1,  1,  0,  2,  5,  5,  5, 
     3,  3,  5,  5,  5,  3,  6,  7,  6,  8,  6,  8,  
     6,  8,  6,  9,  9, 10, 10,  9, 10,  9,  9, 11
]
e = [
     0,  2,  2,  0,  1,  0,  0,  2,  0,  3,  5,  3,  
     4,  4,  3,  4,  3,  4,  8,  8,  6,  6,  7,  6,  
     8,  6,  8,  9,  9,  9, 10, 10, 10, 10,  9, 10
]
f = [
     1,  0,  2,  2,  2,  1,  1,  2,  2,  5,  5,  5,  
     3,  3,  5,  5,  5,  5,  6,  7,  6,  8,  7,  8,  
     6,  8,  6,  9,  9, 10, 10,  9, 11, 10,  9, 11
]
g = [
     1,  1,  2,  2,  2,  1,  1,  2,  2,  4,  5,  5,  
     4,  4,  5,  3,  5,  5,  6,  4,  4,  8,  7,  8,  
     6,  8,  6,  9, 11,  9, 10,  9, 11, 10,  9, 11
]

w = [0.417, 0.278, 0.444, 0.333, 0.333, 0.361, 0.333]

topics = np.vstack(
    (a, b, c, d, e, f, g)
)
weights = np.array(w)

次のような結果になります。

[ 1  0  2  2  2  1  1  0  2  5  5  5  3  3  5  4  5  5  6  7  6  8  7  8  6  8  6  9  9  9 10  9 11 10  9 11]

ざっと見る限りまともに動いてそうに見えます
さすがに手計算をするのは手間なので、もし気になるようなら手元での確認をお願いします。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.50%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 受付中

    連続した数字の和を求めたい

    Python2.7を使っています。 text.txtというファイルがあり、中には数字が羅列しています。 1234680...といった具合です。 これらの和を求めようとしていま

  • 解決済

    pythonでfor文の多重構造を作る

    前提・実現したいこと リストから数字を1つ取り出し、数字の数だけランダムな数字を発生させる。それらの数字の総和をとる。 この動作をリストの要素回行う。 最後にリストのそれぞれ

  • 解決済

    pythonのコードについての質問

    pythonについての質問です gensimのチュートリアルのコードです >>>from gensim import corpora, models, similariti

  • 受付中

    ターミナルで実行するのに時間がかかりすぎる

    ターミナルで実行するのに時間がかかりすぎます。 画像圧縮のアルゴリズムを書いています。 N × N ピクセルのグレースケール画像があり各ピクセルの画素値は 0 から 255

  • 解決済

    1行で表せるコードを分割して書きたい

    1行で表せるコードを分割して書きたいです。 # coding: utf-8 import itertools a = [2,5,7,3,6] b = [1,3,6,8,4]

  • 解決済

    一番初めの要素が大きいもの順に並び替えたい

    一番初めの要素が大きいもの順に並び替えたいです。 total_ans =[ ( sum( [ dict( zip( a, b ) )[v] for i, v in enumer

  • 解決済

    Pythonのtkinterのエラー

    2017-12-19 15:48:07.790 python[51777:1128073] *** Terminating app due to uncaught exceptio

  • 解決済

    関数について。 (コードの短縮)

     前提・実現したいこと 関数を使ったコードの短縮。 pythonの学習を始めたのですが書いたコードを関数を使って短くしたいと思ってもどうやればいいのか検討がつきません。どこで関数を

同じタグがついた質問を見る

  • Python

    8008questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。