블록체인 소개 - (6) 퍼블릭 블록체인과 프라이빗 블록체인

|

블록체인 분류

블록체인은 크게 3가지 형태로 분류할 수 있습니다. 누구라도 자유롭게 노드 참여가 가능한 퍼블릭 블록체인(Public Blockchain), 허가된 노드들만 참여가 가능한 프라이빗 블록체인(Private Blockchain), 여러 기관들이 컨소시움을 이루어서 블록체인 네트워크를 같이 운영하는 컨소시엄 블록체인(Consortium Blockchain)으로 나눌 수 있습니다. 하지만, 프라이빗 블록체인과 컨소시움 블록체인은 그 성격이 유사하기 때문에 보통 블록체인을 나눌 때는 퍼블릭 블록체인과 프라이빗 블록체인으로 나눕니다.


퍼블릭 블록체인

퍼블릭 블록체인은 누구나 노드 참여가 가능하기 때문에, 악의가 있는 참가자를 가려내거나 대처해야 하는 아주 큰 이슈가 존재합니다. 이는 블록체인이 등장하기 이전부터 비잔틴 장군 문제(Byzantine Generals’ Problem)라는 난제로 유명했었고, 크게 다음과 같은 문제가 걸림돌이었습니다.

  • p2p 시스템에서는 각 노드간 정보 도달에 시간 차이가 존재한다. 또는 도달하지 못하는 경우도 발생할 수 있다.
  • 악의가 있는 노드에 의해 잘못된 정보가 전달 될 수 있다.

블록체인도 비잔틴 장군 문제를 고스란히 갖고 있고, 비트코인에서는 작업 증명(PoW, Proof of Work)이라는 합의 알고리즘을 도입하여 이 문제를 해결했습니다. 물론 PoW가 비잔틴 장군 문제의 유일한 해결책은 아니기 때문에 PoW 이외의 합의 알고리즘(예를 들면 PoS 등)을 채택하고 있는 블록체인 기술들도 늘어나고 있는 추세입니다.

PoW나 PoS 등의 합의 알고리즘은 추가 포스팅을 통해 설명을 하도록 하겠습니다.

암튼, 퍼블릭 블록체인은 노드 참여가 자유롭다는 점 때문에 성능이나 PoW 도입으로 인한 다양한 단점들을 많이 갖고 있습니다. PoW의 단점들도 추가 포스팅으로 같이 설명하도록 하겠습니다.

퍼블릭 블록체인은 많은 노드들의 참여가 보장될수록 보안성이 강력해지기 때문에 참여한 노드들에게 보상을 줘야 하는 p2p 경제 원칙을 따르고 있습니다. (p2p 경제 원칙의 대표적인 사례로 비트토렌트같은 경우는 파일 공유를 하면 다운로드 속도를 보상으로 제공합니다.) 따라서 그 보상을 코인으로 제공하는 경우가 대다수이기 때문에 내부 화폐가 필요하다고 볼 수 있습니다.

퍼블릭 블록체인은 알고리즘 변경이나 버그 수정, 엔진 업그레이드 등이 상당히 어렵습니다. 만약 수정을 하게 될 경우 최악의 경우에는 하드포크(Hard-fork)가 발생하게 되어 새로운 체인이 만들어지는 경우도 발생할 수 있습니다.


프라이빗 블록체인

프라이빗 블록체인은 허가된 노드들만 네트워크에 참여가 가능합니다. 이를 관리하는 멤버쉽 서비스가 따로 존재하며 특정 기업에서 프라이빗 블록체인 기반으로 서비스를 제공하면, 해당 블록체인의 노드들은 서비스를 제공하는 기업에서 전부 구동시킬 가능성이 높습니다. (참고로 해당 기업의 서비스에 회원 가입이나 로그인이 자유롭다고 해서 해당 서비스가 퍼블릭 블록체인인 것은 아닙니다. 서비스의 회원이 아닌 ‘노드(Node)’로서 참여가 자유로울 때 퍼블릭 블록체인이 되는 것입니다.)

프라이빗 블록체인은 이미 신뢰할 수 있는 노드들만 참여가 가능하기 때문에, 악의가 있는 참가자를 가려내는 것보다는 성능이나 결제 완료성(Settlement Finality)이 훨씬 중요합니다. 그래서 성능과 결제 완료성 문제를 해결한 합의 알고리즘인 PBFT(Practical Byzantine Fault Tolerance)를 주로 사용합니다.

PBFT는 다수결로 의사를 결정하고, 그 다음에 블록을 생성하기 때문에 체인의 분기가 발생하지 않습니다. 그래서 결제 완료성이 보장되며, PoW와 같이 정답을 찾을 때까지 반복적인 연산을 하지 않기 때문에 훨씬 고성능으로 동작할 수 있습니다.

네트워크에 참여한 모든 노드들은 특정 기업에서 자체적으로 운영하는 노드일 가능성이 높기 때문에 퍼블릭 블록체인과 같은 보상 시스템이 필요없습니다. 즉, 내부 화폐가 없더라도 잘 동작할 수 있습니다.

또한 모든 노드들을 특정 기업에서 컨트롤할 수 있기 때문에 코드 수정이나 엔진 업그레이드 등이 퍼블릭 블록체인에 비해 훨씬 더 쉽습니다.

블록체인 소개 - (5) 대표적인 블록체인 기술(비트코인, 이더리움, 하이퍼레저)간 비교

|

비트코인, 이더리움, 하이퍼레저 비교

퍼블릭 블록체인과 프라이빗 블록체인의 설명에 앞서 먼저 퍼블릭 블록체인(Public Blockchain)의 대표적인 기술인 비트코인(Bitcoin Core)과 이더리움(Ethereum), 그리고 프라이빗 블록체인(Private Blockchain)의 대표적인 기술인 하이퍼레저(Hyperledger)의 특징을 간단히 살펴보도록 하겠습니다.

항목 비트코인 이더리움 하이퍼레저
분류 퍼블릭 블록체인 퍼블릭 블록체인 프라이빗 블록체인
노드로써 참가 자격 누구나 참여 가능 누구나 참여 가능 멤버십 서비스를 통해 허가된 노드만 참여 가능. PKI 기반 증명서 발행
합의 알고리즘 PoW PoW (향후 PoS 도입 예정) PBFT
결제 완료성 없음 없음 있음
성능 약 10분마다 블록 생성 약 12초마다 블록 생성 갱신시 합의를 확정하기 때문에 우수한 성능 보장
트랜잭션 은닉화 트랜잭션 정보는 공개 트랜잭션 정보는 공개 트랜잭션 정보의 공개/암호화를 선택 가능
스마트 컨트랙트 거의 없다시피 함. 제한적인 용도로 사용 가능 이더리움 버추얼 머신(EVM, Ethereum Virtual Machine)에서 동작하는 스마트 컨트랙트 구현 가능. Solidity 언어로 개발 체인 코드(Chaincode)를 통해 스마트 컨트랙트 구현 가능. Go 및 Java로 개발
최소 구성 대수 1대부터 가능. 장애 복구를 위해 최소 2대 필요 1대 부터 가능. 장애 복구를 위해 최소 2대 필요 장애 복구를 위해 최소 4대 필요

위에서 ‘결제 완료성(Settlement Finality)’은 결제가 완료될 때까지의 불확실성을 의미합니다. 비트코인이나 이더리움의 경우 합의 알고리즘을 PoW(Proof of Work) 방식을 이용하는데, PoW 방식은 체인이 분기되었을 때 가장 긴 체인을 올바른 체인으로 선택합니다. 체인 분기가 아주 잦은 건 아니지만 종종 발생하는 편이기 때문에 비트코인의 경우 거래가 확정되더라도 6블럭 정도를 추가로 기다리지 않으면 확실한 결과를 얻을 수가 없습니다.

Keras - 이진 데이터 분류 예제

|

Keras를 이용한 이진 데이터(Binary Data) 분류하기 예제 코드

데이터셋은 아래의 코드를 이용해서 랜덤으로 생성합니다.

import numpy as np

x_train = np.random.random((1000, 12))
y_train = np.random.randint(2, size=(1000, 1))

x_test = np.random.random((100, 12))
y_test = np.random.randint(2, size=(100, 1))

import matplotlib.pyplot as plt

plot_x = x_train[:, 0]
plot_y = x_train[:, 1]
plot_color = y_train.reshape(1000, )

plt.scatter(plot_x, plot_y, c=plot_color)
plt.show()

Image


사실 위 데이터는 완전 무작위로 생성한 값이기 때문에 특정 패턴이 없습니다. 그래서 머신 러닝에서 활용하기에 그리 좋은 케이스는 아닙니다. 하지만 이런 무작위 데이터는 아주 쉽게 만들 수 있기 때문에 연습용으로 활용하거나, 실제 데이터 분석을 하기 전 프로토타입 구현용으로는 괜찮은 것 같습니다.


퍼셉트론 신경망 예제

import numpy as np
from keras.models import Sequential
from keras.layers import Dense

x_train = np.random.random((1000, 12))
y_train = np.random.randint(2, size=(1000, 1))

x_test = np.random.random((100, 12))
y_test = np.random.randint(2, size=(100, 1))

model = Sequential()
model.add(Dense(1, input_dim=12, activation='sigmoid'))

model.compile(optimizer='rmsprop', loss='binary_crossentropy',
              metrics=['accuracy'])

hist = model.fit(x_train, y_train, epochs=100, batch_size=30)

import matplotlib.pyplot as plt

fig, loss_ax = plt.subplots()

acc_ax = loss_ax.twinx()
loss_ax.set_ylim([0.0, 1.0])
acc_ax.set_ylim([0.0, 1.0])

loss_ax.plot(hist.history['loss'], 'y', label='train loss')
acc_ax.plot(hist.history['acc'], 'b', label='train acc')

loss_ax.set_xlabel('epoch')
loss_ax.set_ylabel('loss')
acc_ax.set_ylabel('accuracy')

loss_ax.legend(loc='upper left')
acc_ax.legend(loc='lower left')

plt.show()

loss_and_metrics = model.evaluate(x_test, y_test, batch_size=30)
print('loss_and_metric: {}'.format(loss_and_metrics))

실행 결과는 다음과 같습니다.

Image


다층 퍼셉트론 신경망 예제

import numpy as np
from keras.models import Sequential
from keras.layers import Dense

x_train = np.random.random((1000, 12))
y_train = np.random.randint(2, size=(1000, 1))

x_test = np.random.random((100, 12))
y_test = np.random.randint(2, size=(100, 1))

model = Sequential()
model.add(Dense(64, input_dim=12, activation='relu'))
model.add(Dense(1, activation='sigmoid'))

model.compile(optimizer='rmsprop', loss='binary_crossentropy',
              metrics=['accuracy'])

hist = model.fit(x_train, y_train, epochs=100, batch_size=30)

import matplotlib.pyplot as plt

fig, loss_ax = plt.subplots()

acc_ax = loss_ax.twinx()
loss_ax.set_ylim([0.0, 1.0])
acc_ax.set_ylim([0.0, 1.0])

loss_ax.plot(hist.history['loss'], 'y', label='train loss')
acc_ax.plot(hist.history['acc'], 'b', label='train acc')

loss_ax.set_xlabel('epoch')
loss_ax.set_ylabel('loss')
acc_ax.set_ylabel('accuracy')

loss_ax.legend(loc='upper left')
acc_ax.legend(loc='lower left')

plt.show()

loss_and_metrics = model.evaluate(x_test, y_test, batch_size=30)
print('loss_and_metric: {}'.format(loss_and_metrics))

실행 결과는 다음과 같습니다.

Image

사실 데이터셋이 완전 무작위이이 때문에 많은 결론을 도출할 수는 없지만, 여기서 알 수 있는 것은 다층 신경망이 단층 신경망보다는 학습 속도가 훨씬 더 빠르다는 것을 알 수 있습니다.

Keras - 수치 예측하기 예제

|

Keras를 이용한 수치 예측하기 예제

다음과 같은 랜덤 데이터셋을 만들었을 때, 그 데이터를 학습한 다음 향후 들어오는 입력값을 예측하는 예제코드입니다.

import numpy as np

x_train = np.random.random((1000, 1))
y_train = x_train * 2 + np.random.random((1000, 1)) / 3.0

x_test = np.random.random((100, 1))
y_test = x_test * 2 + np.random.random((100, 1)) / 3.0

import matplotlib.pyplot as plt

plt.plot(x_train, y_train, 'ro')
plt.plot(x_test, y_test, 'bo')
plt.legend(['train', 'test'], loc='upper left')
plt.show()

Image

입력값 X에 2를 곱해서 Y 값을 만들어내는 식이기 때문에 `Y = w * X + b’ 형태의 수식으로 표현할 수 있으며, w는 2에 가깝고, b는 0.16에 가까워지면 정답에 근접해집니다.


일반적인 선형회귀 모델(numpy 활용)

import numpy as np
from sklearn.metrics import mean_squared_error

x_train = np.random.random((1000, 1))
y_train = x_train * 2 + np.random.random((1000, 1)) / 3.0

x_test = np.random.random((100, 1))
y_test = x_test * 2 + np.random.random((100, 1)) / 3.0

x_train = x_train.reshape(1000, )
y_train = y_train.reshape(1000, )
x_test = x_test.reshape(100, )
y_test = y_test.reshape(100, )

w = np.cov(x_train, y_train, bias=1)[0, 1] / np.var(x_train)
b = np.average(y_train) - w * np.average(x_train)

print('w:{0}, b:{1}'.format(w, b))

y_predict = w * x_test + b
mse = mean_squared_error(y_test, y_predict)
print('mse: {}'.format(mse))


퍼셉트론 신경망 모델

import numpy as np
from keras.models import Sequential
from keras.layers import Dense

x_train = np.random.random((1000, 1))
y_train = x_train * 2 + np.random.random((1000, 1)) / 3.0

x_test = np.random.random((100, 1))
y_test = x_test * 2 + np.random.random((100, 1)) / 3.0

model = Sequential()
model.add(Dense(1, input_dim=1))

model.compile(optimizer='rmsprop', loss='mse')

hist = model.fit(x_train, y_train, epochs=50, batch_size=10)
w, b = model.get_weights()
print('w:{0}, b:{1}'.format(w, b))

import matplotlib.pyplot as plt

plt.plot(hist.history['loss'])
plt.ylim(0.0, 1.5)
plt.xlabel('epoch')
plt.ylabel('loss')
plt.legend(['train'], loc='upper left')
plt.show()

loss = model.evaluate(x_test, y_test, batch_size=10)
print('loss: {0}'.format(loss))

결과는 다음과 같습니다.

w:[[2.009994]], b:[0.16119921]
...
loss: 0.010309214843437076

Image


다층 퍼셉트론 신경망 모델

import numpy as np
from keras.models import Sequential
from keras.layers import Dense

x_train = np.random.random((1000, 1))
y_train = x_train * 2 + np.random.random((1000, 1)) / 3.0

x_test = np.random.random((100, 1))
y_test = x_test * 2 + np.random.random((100, 1)) / 3.0

model = Sequential()
model.add(Dense(64, input_dim=1, activation='relu'))
model.add(Dense(1))

model.compile(optimizer='rmsprop', loss='mse')

hist = model.fit(x_train, y_train, epochs=50, batch_size=10)

import matplotlib.pyplot as plt

plt.plot(hist.history['loss'])
plt.ylim(0.0, 1.5)
plt.xlabel('epoch')
plt.ylabel('loss')
plt.legend(['train'], loc='upper left')
plt.show()

loss = model.evaluate(x_test, y_test, batch_size=10)
print('loss: {0}'.format(loss))

결과입니다.

...
loss: 0.008995027653872967

Image

Keras - 다층 퍼셉트론(MLP, Multi-Layer Perception)

|

Keras 다층 퍼셉트론 구현

Keras에서 다층 퍼셉트론은 다음과 같은 코드를 이용해서 구현합니다.

model = Sequential()
model.add(Dense(12, input_dim=8, activation='relu'))
model.add(Dense(8, activation='relu))
model.add(Dense(1, activation='sigmoid'))

model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

첫 번째 라인의 Sequential()으로 다층 퍼셉트론 형태를 만들겠다는 의미이며, 그 다음 라인의 Dense()들이 각 계층을 의미합니다. 또한 마지막에 compile() 과정을 거쳐 모델을 생성합니다.


Dense 파라메터

Dense() 계층을 생성할 때 각 파라메터는 다음과 같은 의미를 가집니다.

model.add(Dense(12, input_dim=8, activation='relu'))

맨 앞의 숫자 12는 해당 계층의 노드 개수입니다. input_dim=8의 경우 입력단에 8개의 데이터 항목이 존재한다는 의미이며, 보통 첫 번째 Layer에서만 input_dim 파라메터를 입력합니다. activation은 활성화 함수를 의미합니다.

활성화 함수는 다음과 같은 종류를 사용할 수 있습니다.

  • linear : 기본값이며, 가중치 결과값이 출력으로 그대로 나옵니다.
  • relu : ReLU 함수입니다. 은닉층에서 주로 사용합니다.
  • sigmoid : 주로 출력층에서 사용합니다.
  • softmax : 출력값들의 합이 1.0이 되도록 하는 함수로 보통 출력층에서 사용합니다.


compile 옵션

compile() 함수의 옵션은 각각 다음과 같습니다.

  • loss : 현재 가중치 세트를 평가하는데 사용하는 손실 함수입니다.
  • optimizer : 최적의 가중치를 찾는 최적화 알고리즘으로, adam은 효율적인 경사 하강법 알고리즘 중 하나입니다.
  • metrics : 평가 척도를 의미하며, 일반적으로 accuracy를 사용합니다.