머신러닝

4-11 죄수의 딜레마 (Prisoner’s Dilemma) 로직화 및 머신 러닝 계산

coding art 2021. 7. 6. 16:57
728x90

게임이론이나 경제학 또는 범죄수사에서 유명한 죄수의 딜레마 문제를 다루어 보자. 두 명의 범죄자들이 잡혀왔으나 기소하기 위해서는 증거가 부족한 상태라 검찰은 범죄자들이 서로 짜고 칠 수 없도록 각각 독방에 가둔 후 형량 바게인을 위한 거래를 제안한다.

 

1) 둘 다 서로가 배신할 경우에는 각각 2년의 형량으로 감형하여 구형한다.

2) 한명이 배신하여 자백을 하고 다른 범죄자가 묵비권을 행사하면 자백한 범죄자는 형량 없이 풀려나고 묵비권을 행사하는 범죄자는 3년의 형량을 구형한다.

3) 둘 다 묵비권을 행사하여 추가적인 증거 수집이 불가능한 경우에는 둘 다 1년형을 구형할 수밖에 없다.

 

결과적으로 인간의 또는 범죄자의 심리 상 두 범죄자는 자백을 하기 쉽다. 만약 상대방이 묵비권을 행사하는데 자신만 자백하게 되면 자신이 엄청 유리해지고, 반대로 상대방이 자백하는데 자신이 침묵하게 되면 자신이 엄청 불리해지기 때문이다.

 

실제 적용해 보면 대부분 둘 다 자백하게 되는 경우가 많다고 한다. 이 이론은 게임 이론에서 연구되어 경제학 분야의 협상 전술에 많이 사용된다고 하며 범죄자들 모두가 자백을 할 수밖에 없게 되는 그 상황을 노벨 경제학 수상자로 유명한 John Nash의 이름을 따서 Nash의 균형이라고 한다.

 

형량 3년을 1.0 으로 하여 normalization 해서 다음과 같이 표를 작성해 보자.

죄수의 딜레마 문제는 AND OR XOR 로직과는 달리 소숫점 이하 값들을 포함한다. 논리 측면에서 보면 범죄자 자신이 풀려날 경우만 무죄고 나머지는 다 유죄로서 경중이 있게 된다.

 

이 문제를 풀어 보기위한 파이선 코드는 뉴럴 네트워크 코드에서 압력 데아타는 그대로 두고 출력 데이터만 위 표에서 A 범죄자의 구형량으로 입력하자. learning rate 0.5 학습횟수는 10,000회로 두자.

뉴럴 네트워크 코드를 사용해서 계산한 hypothesis 결과를 관찰해 보자. 구형량을 정확하게 tracking 함을 알 수 있다. 이 문제는 AND 또는 OR 또는 XOR 문제와 또 다르기 때문에 뉴럴 네트워크 코드를 적용하였으며 선형회귀법에 의해서도 계산은 가능하나 해 보면 오차가 좀 큰 편이다. 무난하게 계산이 이루어지는 것으로 보아 학습에 별 문제는 없는 듯하다. 하지만 특이한 사항으로 cost 함수의 값이 0.0 이 아닌 0.31에 수렴하고 있다. 죄수의 딜레마 문제가 여타의 로직문제와 다르기 때문에 가급적이면 hypothesis 곡면을 한번 그래픽 처리해 볼 필요가 있을 듯하다.

#Nash_logic_nn_01.py

import tensorflow as tf
import numpy as np

tf.set_random_seed(777)  # for reproducibility
learning_rate = 0.5

x_data = [[0, 0], [0, 1], [1, 0], [1, 1]]
y_data = [[0.33], [0.0], [1.0], [0.67]]

x_data = np.array(x_data, dtype=np.float32)
y_data = np.array(y_data, dtype=np.float32)

X = tf.placeholder(tf.float32, [None, 2])
Y = tf.placeholder(tf.float32, [None, 1])

W1 = tf.Variable(tf.random_normal([2, 2]), name='weight1')
b1 = tf.Variable(tf.random_normal([2]), name='bias1')
layer1 = tf.sigmoid(tf.matmul(X, W1) + b1)

W2 = tf.Variable(tf.random_normal([2, 1]), name='weight2')
b2 = tf.Variable(tf.random_normal([1]), name='bias2')
hypothesis = tf.sigmoid(tf.matmul(layer1, W2) + b2)

#cost/loss function
cost = -tf.reduce_mean(Y * tf.log(hypothesis) + (1 - Y) *
                       tf.log(1 - hypothesis))

train = tf.train.GradientDescentOptimizer(learning_rate=learning_rate).minimize(cost)

#Launch graph
with tf.Session() as sess:
    #Initialize TensorFlow variables
    sess.run(tf.global_variables_initializer())

    for step in range(10001):
        sess.run(train, feed_dict={X: x_data, Y: y_data})
        if step % 2000 == 0:
            print(step, sess.run(cost, feed_dict={
                  X: x_data, Y: y_data}), sess.run([W1, W2]), sess.run([b1, b2]))

    #Hypothesis report
    h = sess.run(hypothesis,
                       feed_dict={X: x_data, Y: y_data})
    print("\nhypothesis: ", h)