진화론 이야기 - 진화론이 '완벽한 진리'일까?

창조론자들이 보기에 창조론은 '완벽한 진리'입니다. 신이 쓴 책(성경)에 신의 존재와 그 신의 창조작업이 명시되어 있으니까 말입니다(물론 이런 논증은, 신이 신을 증명하는 '순환논리'일 뿐이지만, 창조론자들에게 중요한 것은 논리가 아니라 믿음이죠).
그때문에 창조론자들은, 진화론자들도 진화론을 '완벽한 진리'라 여기고 있다고 생각하고 있습니다. 그래서 가끔씩 바뀌는 진화론에 대해 '그렇게 계속 바뀌는 진화론이 진리라는 것 역시 진화론에 대한 믿음이 아니냐'며 진화론을 창조론과 동급인 믿음으로 폄하하곤 합니다.
하지만 그런 반문은 결국 사이비과학인 창조과학과, 진화론을 포함하는 진짜과학을 구분하지 못한다는 반증일 뿐입니다. 왜냐하면 과학이란 것 자체가 자꾸 변하는 학문 - 완벽한 진리에 한발짝씩 다가가는 학문이기 때문입니다.

진화론은 현재까지 발견된 증거들을 가장 잘 설명하는 이론입니다. 하지만 과학자들은 진화론을 '완벽한 진리'라고 하지는 않습니다. 과학은 항상 반증될 가능성이 남아 있으며, 그러한 반증이 나오지 않는지 끊임없이 관찰을 해야 합니다.
언젠가는 진화론으로 설명할 수 없는 새로운 현상이 관측될 지도 모릅니다. 그러나 그렇다고 해서 과학에 대한, 진화론에 대한 불신을 가질 필요는 없습니다. 새로운 현상을 설명할 수 있는 새로운 이론은 기존 진화론보다 완벽한 진리에 한발짝 더 가까운 이론이 될 테니까 말입니다.
그렇지 않고 '진화론은 완벽한 사실이다'라는 오만에 빠져있는 것이야말로 완벽한 진리에 다가갈 기회를 차버리는 가장 비과학적인 태도입니다.

마지막으로 제목에 대한 답을 하자면,
진화론이 완벽한 진리인지 아닌지는 알 수 없습니다. 그러나 창조론보다는 완벽한 진리에 훨씬 가깝습니다. 그리고 시간이 지날수록 완벽한 진리에 점점 다가가고 있습니다.

진화론 이야기 - 남녀탐구생활 - 쇼핑



동영상은 요즘 인기있는 남녀탐구생활의 한 꼭지입니다. 백화점에서 남자는 처음 들른 가게에서 물건이 '너무 나쁘지 않으면' 사는 반면, 여자는 '여러 가게를 들러보고 가장 좋은 것'을 산다는 점을 약간의 과장과 함께 보여주고 있습니다.

원시시대, 남자는 수렵을, 여자는 채취를 하는 식으로 서로 분업화가 되어 있었습니다.
어느날 아침, 한 마을의 남자들은 동물을 잡으러, 여자들은 과일을 모으러 집을 나섰습니다.

한동안 길을 걷다가, 여자들은 과일이 열린 나무를 발견했습니다. 이때 여자들의 최선의 선택은 무엇일까요?
열매를 따서 돌아가는 것은 하루일을 끝내기에는 너무 이르기에 시간낭비입니다. 그렇다고 열매를 따서 들고 다니기에는 너무 무거울뿐 아니라, 더 좋은 과일이 발견되면 버리게 되겠죠. 결국 여자들의 가장 좋은 선택은 나무의 위치를 기억해둔 후 계속 다른 과일을 찾아다니는 것입니다. 그리고 돌아올때 가장 좋았던 나무들 몇군데만 들러 과일을 따오는 것입니다.

한동안 길을 걷다가, 남자들은 조그만 토끼를 발견했습니다. 이때 남자들의 최선의 선택은 무엇일까요?
여자들처럼 더 큰 사냥감을 찾기 위해 지나쳤다가, 돌아오는 길에 들른다면 그 토끼가 그자리에 있으리라는 보장은 전혀 없습니다. 결국 최선의 선택은 그 토끼를 잡아서 나머지 사냥길동안(무겁지만) 들고 다니는 것입니다. 비록 코끼리를 잡아 지금 잡은 작은 토끼를 버리고 오는 한이 있어도 말이죠.

그러한 이유로 여자들에게는 여러 곳을 들러 가장 좋은 것을 찾는 본능이, 남자들에게는 처음 들른 곳에서 모든 것을 해결하려는 욕구가 생긴 것입니다.

이것을 진화론적으로 설명하는 이유는, 이러한 본능이 후천적으로 길러진 것이 아니라 선천적이기 때문이죠. 남자라도 어린 시절에는 백화점에 주로 어머니와 갑니다. 그래서 어린 시절부터 어머니의 '여러곳에 들러서 가장 좋은 것 고르기'에 많이 접합니다. 그럼에도 불구하고 그 남자아이는 나중에 '처음 들른 곳에서 물건사기' 버릇이 들고 맙니다.
그러므로 이러한 본능은 선천적으로 유전자에 박혀 있다고 봐야겠죠.

진화론 이야기 - 매냐 비둘기냐

어떤 동물무리가 있습니다. 같은 종이지만 그들 중에는 조금더 호전적인 개체(매파)가 있는가 하면 비교적 평화로운 개체(비둘기파)가 있습니다.

먹이를 사이에 두고 두 비둘기파가 만난 경우 두 비둘기파는 서로 대치를 합니다. 어느 한쪽이 지쳐 물러나야 대치가 끝납니다.
먹이를 사이에 두고 두 매파가 만난 경우 두 매파는 서로 싸움을 합니다. 결국 어느 한쪽이 심한 상처를 입을 때까지 싸움을 벌입니다.
먹이를 사이에 두고 매파와 비둘기파가 만난 경우 매파의 공격에 비둘기파는 달아나고 맙니다.

이와 같은 상황에서 저 동물무리가 진화했을때 도달하게 될 안정된 전략(strategy : 매파전략인지 비둘기파전략인지)을 ESS(Evolutionarily Stable Strategy)라 합니다. 과연 저 동물무리의 ESS는 어떤 상황이 될까요.

ESS를 계산하기 위해서는 각 상황에 대해 각 개체가 얻을 수 있는 이익을 수량화시키는 것이 필요합니다.


승자
패자
비둘기파vs비둘기파
먹이(50)+대치(-10)
대치(-10)
매파vs매파
먹이(50)
큰 부상(-100)
매파vs비둘기파
먹이(50)
0

만약 동물무리 전체가 비둘기파로 구성되어 있었다면 그들은 항상 먹이를 사이에 두고 대치만 할 것입니다. 만약 승률이 50%라면 이겼을때 40점, 졌을때 -10점으로 평균 15점을 얻게 됩니다.
이 동물무리 안에 매파가 하나 생겼다면*, 이 매파는 항상 비둘기파와 대결하여 승리하게 됩니다. 즉 이 매파는 50점으로 비둘기파의 15점보다 훨씬 높습니다. 즉 매파 유전자가 무리에 퍼져나갑니다.
그리하여 매파가 무리 전체에 퍼져나간다면, 이제 매파는 항상 매파와만 만납니다. 즉 이겼을떄 50점, 졌을때 -100점으로 (역시 승률 50%라면) 평균 -25점을 얻죠.
이 동물무리 안에 비둘기파가 하나 생겼다면*, 이 비둘기파는 항상 매파와 대결하여 패배하게 됩니다. 하지만 그렇다고 해도 (항상 달아나서) 0점으로, 매파의 -25점보다는 훨씬 높습니다. 즉 비둘기파 유전자가 무리에 퍼져나갑니다.

실제로는 이렇게 진동하는 것이 아니라 일정한 비율로 수렴하게 됩니다. 위와 같은 경우, 매파와 비둘기파는 7:5의 비율로 평형을 이루며 이때 모든 개체들의 점수는 6.25입니다.(물론 이겼을 때와 졌을 때의 점수를 바꾸면 비율은 달라집니다).

물론 이것은 극히 간단한 모형이지만, '왜 같은 종에서도 호전적인 개체와 덜 호전적인 개체가 공존하는가'에 대한 진화론적인 대답은 될 수 있을 것입니다.

출처 : 이기적 유전자

* '콩심은데 콩난다'는 속담도 있지만, 진화론에서는 '콩심은데 거의 콩난다'가 맞습니다. 부모가 모두 매파(또는 비둘기파)라도 그 자손은 비둘기파(또는 매파)가 나올 수 있습니다.

GA - CNNC를 실은 꼬마자동차[3] - 결과

11. 결과 1
우선 앞과 같은 방식으로 돌길꼬마자동차를 공진화시켰습니다. 100세대 후 최고 적응도를 얻은 꼬마자동차의 성적표입니다.

Generation:99 MaxScore:-2440 Collision:254 MinScore:-2561 Move:264

최고성적의 꼬마자동차도 64개의 돌길을 지나며 264(평균 4.125)칸만을 이동할 수 있었습니다. 그동안 254번이나 장애물과 충돌했군요.

꼬마자동차와 함께 진화된 돌길을 살펴보겠습니다. 다음은 돌길의 앞부분만을 그린 것입니다.

오른쪽 끝의 푸른 점이 꼬마자동차의 출발점입니다. 저 위치로부터 꼬마자동차는 앞쪽, 왼쪽앞, 오른쪽앞으로 이동할 수 있습니다. 그런데 보시다시피 자동차가 갈 수 있는 곳은 모두 장애물로 덮여 있습니다. 꼬마자동차가 장애물을 통과할때 기름 5씩 들어가므로 4칸만 움직이면 기름이 떨어져 버리죠.
이런 돌길을 통과할 수 있는 꼬마자동차가 진화될 수 없습니다. 돌길에 대해 약간의 제한이 필요하겠군요.

12. 결과 2
꼬마자동차는 앞의 세 칸들 중 하나로 이동할 수 있습니다. 앞의 세 칸 중 하나가 장애물이 아니면 앞으로 이동할 수 있는 것입니다. 그러므로 돌길을 만들때 장애물 세개가 연이어 놓이는 것을 방지했습니다.
그 결과는 다음과 같습니다.

Generation:99 MaxScore:12798 Collision:0 MinScore:-2561 Move:1280

확실히 아까보다는 성적이 좋아졌군요. 그런데 64개 돌길을 지나면서 1280(평균 20)칸을 움직였습니다. 결국 초기 가지고 있던 기름만 다 사용한 것이군요. 이유가 무엇일까요.


위에서 보다시피 꼬마자동차의 앞을 모두 막진 않았지만, 기름통으로 갈 수 있는 길은 철저히 막혀 있습니다. 최소한 한개의 장애물을 밟지 않고는 기름을 얻을 수 없는 구조가 되어 버렸습니다.
조금 더 돌길에 제한이 필요하겠군요.

13. 결과 3
이번에는 각 연료통으로 갈 수 있는 길을 확보해 주었습니다. 100턴 이후 꼬마자동차의 성적표입니다.

Generation:99 MaxScore:63998 Collision:0 MinScore:-2551 Move:6400

보시다시피 길이 100인 돌길 64개, 6400칸을 장애물과 충돌 없이 움직이는데 성공했습니다.

100턴이 지날 때까지 각 세대 최고 적응도의 꼬마자동차가 장애물과 충돌한 횟수를 그래프로 그렸습니다. 이것이 공진화의 전형적인 패턴입니다.
처음 돌길의 진화로 꼬마자동차들이 피할수 없는 장애물패턴을 만듧니다(충돌횟수가 증가합니다). 그 후에는 꼬마자동차의 진화로 그 장애물을 피합니다(충돌횟수가 감소합니다). 다시 돌길의 새로운 패턴 발견(충돌증가), 꼬마자동차의 패턴 돌파(충돌감소)가 반복되며 꼬마자동차돌길의 적응도가 증가합니다. 다만 여기서는 꼬마자동차가 중심이기에 돌길에 약간의 제한을 주어 꼬마자동차의 진화를 돕는 쪽으로 유도했습니다.

지적설계론은 지적설계자를 모욕하는 행위 - 고래

향유고래

모두들 아시다시피 고래는 바다에서 삽니다. 상어나 다른 물고기들과 마찬가지로 말입니다. 바다에서 가장 큰 향유고래나 바다에서 가장 영리한 돌고래처럼 바다에서는 거의 무적인 동물입니다.
하지만 고래는 다른 물고기들에 비해 치명적인 약점을 가지고 있습니다. 상어를 비롯한 다른 물고기들이 아가미호흡을 하는 반면 고래는 허파로 숨을 쉬어야 한다는 점이죠.

물론 고래는 바다속에서 허파를 가지고 살기 위해 나름대로 몇가지 장치를 가지고 있습니다. 고래 허파의 공기교환율은 90%에 달합니다. 즉 숨을 내쉴때(날숨) 허파는 들이쉴때(들숨)의 1/10로 줄어듧니다(인간의 경우 공기교환률은 20% 정도에 불과합니다.). 고래 근육의 미오글로빈 역시 산소를 저장할 수 있습니다. 그 때문에 고래는 오랜 시간 잠수할 수 있습니다.

그러나 아무리 잠수를 위한 장치가 많더라도 어차피 허파호흡입니다. 평생 물 밖으로 나오지 않고 살 수 있는 상어에 비해 고래는 몇시간에 한번씩은 물 밖으로 나와야 합니다. 그렇지 않으면 '익사하는 물고기'꼴이 될 수밖에 없죠.

그뿐 아닙니다. 깊은 바다와 수면 위를 오가야 하는 고래는 잠수병에 걸릴 수밖에 없습니다. 이 잠수병은 고래 평생에 걸쳐 쌓이는 증상입니다.

상어에게 아가미를 달아줄 수 있었으니 기술이 부족했던 것은 아닐 테고, 물에 사는 동물들 중 왜 고래에게만 허파를 달아주어서 익사의 공포와 잠수병의 고통 속에 놔뒀을까요?

GA - CNNC를 실은 꼬마자동차[2] - 입력과 출력, 교차

5. 꼬마자동차의 신경망 입력
꼬마자동차가 알아야 할 정보는, 바로 앞의 블럭정보, 그리고 연료가 어디 있는지에 대한 정보입니다.
꼬마자동차 CNNC의 입력노드 중 3개는 앞쪽에 어떤 장애물이 있는지(있으면 1, 없으면 -1), 마지막 하나는 연료의 위치를 -1~+1 사이의 float값으로 입력합니다.

procedure Detect(Car car, StoneRoad road)
.. cl := car.Locate.Len
.. cw := car.Locate.Wid

.. // 앞쪽 3칸 블럭정보
.. if road[cl - 1][cw - 1] == ROCK then
..... SetCharge(
car.CNNC, 0, 1) // 0번셀에 입력
.. else
.....
SetCharge(car.CNNC, 0, -1)
.. end
.. if road[cl - 1][cw + 0] == ROCK then
.....
SetCharge(car.CNNC, 1, 1) // 1번셀에 입력
.. else
.....
SetCharge(car.CNNC, 1, -1)
.. end
.. if road[cl - 1][cw + 1] == ROCK then
.....
SetCharge(car.CNNC, 2, 1) // 2번셀에 입력
.. else
.....
SetCharge(car.CNNC, 2, -1)
.. end

.. // 기름통 위치정보(차에서 가장 가까운)
.. fl := road.Fuel(car).Locate.Len
.. fw := road.Fuel(car).Locate.Wid
..
SetCharge(car.CNNC, 3, (fw - cw) / (fl - cl)) // 3번셀에 입력
end

6. 꼬마자동차의 신경망 출력
신경망 출력을 꼬마자동차의 움직임으로 바꾸기 위해 3개의 출력노드를 사용합니다. 그리고 각 출력노드의 출력양에 따라 직진할지 왼쪽이나 오른쪽으로 움직일지 결정하는 것입니다.
그러나 신경망의 특성상 가능하면 노드수를 줄이는 것이 최적화시키는데 도움이 됩니다. 여기서는 출력노드를 두개로 만들어, 더 강한 출력을 보이는 쪽으로 이동시키도록 하겠습니다. 즉,

procedure Action(Car car, StoneRoad road)
.. left = 0
.. right = 0
.. l := GetCharge(car.CNNC, 0);
.. r := GetCharge(car.CNNC, 1);
.. if l > 0 then // 왼쪽으로 움직이려는 경향
..... left := left + l
.. else // -왼쪽(즉 오른쪽)으로 움직이려는 경향
..... right := right - l
.. end .. if r > 0 then // 오른쪽으로 움직이려는 경향
..... right := right + r
.. else // -오른쪽(즉 왼쪽)으로 움직이려는 경향
..... left := left - r
.. end
.. // 출력이 강한 쪽으로 이동
.. rnd := Random(0, 2)
.. if left > rnd then
..... if right > rnd then
........ MoveForwar(car)
..... else
........ MoveLeft(car)
..... end
... else
..... if right > rnd then
........ MoveRight(car)
..... else
........ MoveForwar(car)
..... end
.. end
end


출력노드를 하나로 해 놓고, +1에 가까울수록 왼쪽으로, -1에 가까울수록 오른쪽으로 움직이도록 할 수도 있지만, 생각만큼 수렴이 잘 되지 않더군요. 우선은 출력노드 두개짜리로 실행해 봤습니다.

7. 적응도 계산
위와 같은 식으로 256개의 꼬마자동차와 64개의 돌길 개체를 만듧니다. 이 256개의 꼬마자동차 각각은 64개의 돌길을 통과하고 각 꼬마자동차돌길의 적응도를 결정합니다.
꼬마자동차의 적응도 : 평지로 진입할 때마다 10점추가, 장애물을 통과할때 10점감점
돌길의 적응도 : 자동차가 기름을 먹으면 5점감점, 장애물로 진입하면 10점추가

8. 교차
꼬마자동차의 경우는 앞의 XOR회로와 같은 일반적인 CNNC식 교차를 사용했습니다.
돌길의 경우는 길 전체를 길이 100의 선형유전자로 간주하고 일반적인 일점교차를 사용했습니다.

procedure CrossOver(StoneRoad a, StoneRoad b)
.. cut := Random(1, 99)
.. for l := 0, cut do
..... for w := 0, 11 do
........ tmp := a[l][w]
........ a[l][w] := b[l][w]
........ b[l][w] := tmp
..... end
.. end
end

9. 돌연변이
돌연변이 역시 꼬마자동차의 경우에는 CNNC의 돌연변이 루틴을 사용합니다.
돌길의 돌연변이는 두 단계로 이루어집니다. 첫째, 일정한 확률로 장애물을 만들기(또는 장애물을 없애기), 둘째, 기름통 위치 바꾸기입니다.

procedure Mutantation(StoneRoad gene)
.. for l := 0, 99 do
..... for w := 1, 10 do // 가장자리는 장애물로 유지
........ if MutantRate then
........... if gene[l][w] == ROCK then
.............. gene[l][w] := ROAD
........... else if gene[l][w] == ROAD then
.............. gene[l][w] := ROCK
........... end
..... end
.. end

.. for l := 0, 99 do
..... for w := 1, 10 do // 가장자리는 장애물로 유지
........ if gene[l][w] == FUEL then
........... if MutantRate then
.............. gene[l][w] := ROAD
.............. gene[l][Random(1, 10)] := FUEL
.............. break // w 루프 탈춮
........... end
........ end
..... end
.. end
end

10. 재생산
256개 꼬마자동차들이 모두 64개 돌길에서 달려 본 후 꼬마자동차돌길을 재생산합니다. 역시 꼬마자동차의 경우는 CNNC의 재생산 루틴을 사용했으며(이 경우 상위 8개의 꼬마자동차를 다음 세대에 그대로 복사하는 Elitism을 사용했습니다.)
돌길의 경우에는 T==0.95, Round==4인 토너먼트법(임의로 24=16개의 돌길을 고른 후 95%의 확률로 적응도 높은 쪽이 이기는 토너먼트를 4회 반복)으로 재생산시켰습니다.

GA - CNNC를 실은 꼬마자동차[1] - 공진화와 유전자설계

1. 개요
장애물을 피해 움직이는 꼬마자동차는 이미 앞에서 진화시켜본 적이 있습니다. 8개의 유전자를 가진 자동차들이었죠.
이번에는 8개의 유전자를 가진 꼬마자동차가 아니라 CNNC를 탑재한 꼬마자동차를 진화시키도록 하겠습니다. 기본적으로 바로 앞 3칸의 블럭정보를 받아들여 CNNC에 기초한 신경망을 돌려 다음 행동을 결정하는 것이죠.
하지만 이번 문제에서는 한가지 요인을 더 넣었습니다. '연료'란 개념을 넣었죠.
꼬마자동차는 최대크기 20의 기름통을 가지고 있습니다. 한칸 이동할 때마다 1씩, 그리고 장애물 위를 통과하기 위해서는 5의 기름을 소모합니다.
물론 자동차가 통과해야 할 거리는 100입니다. 그러므로 길 위에는 10칸마다 하나씩 기름통을 10만큼 채울 수 있는 기름이 존재합니다. 그리고 각 자동차들은 다음 기름통의 위치를 감지할 수 있는 감지기를 추가합니다.

2. 공진화
개인의 발전을 위해 라이벌이 필요하듯, 천적들이 서로가 서로의 선택압으로 작용하여 적응도가 높아지는 경우가 있습니다. 이러한 현상을 공진화라고 합니다.
그렇다면 이 꼬마자동차의 천적은 무엇일까요? 이 꼬마자동차가 극복해야 할 대상, 즉 장애물이 깔려있는 돌길 자체가 천적이 되겠죠.
꼬마자동차의 적응도는 '돌길을 얼마나 멀리 갔는가'에 따라 결정됩니다. 반대로 돌길의 적응도는 '자동차들을 얼마나 방해했는가'로 결정할 수 있습니다. '특정한 장애물 패턴'을 가지고 있는 돌길에 많은 자동차들이 발목을 잡힌다면, 그 돌길은 높은 적응도를 갖고 진화적 우위를 차지해서 결국 그러한 '특정한 장애물 패턴'은 점점 많아집니다. 다시 그 '특정한 장애물 패턴'을 돌파할 수 있는 자동차들이 진화적 우위를 차지합니다.

3. 유전자설계 - 꼬마자동차
꼬마자동차의 유전자는 앞의 XOR회로를 진화시키기 위해 사용했던 신경망 그대로입니다. 다만 여기서는 (뒤에서 나올 이유로) 신경세포의 전하량을 0~1이 아니라 -1~+1 사이로 정의했습니다. 이것은 시그모이드함수를 다음과 같이 수정함으로써 간단히 구현됩니다.


4. 유전자설계 - 돌길
돌길의 유전자는, 다음 그림과 같이 설계됩니다. 돌(장애물)과 기름통이 놓여있는 길이 100인 길이죠.



갈색은 장애물, 녹색은 기름통입니다. 그 외의 흰 부분은 장애물 없는 빈 공간입니다.

procedure InitGene(StoneRoad gene)
.. for length := 0, 99 do
..... gene[length][0] := ROCK
..... for width := 1, 10 do
........ gene[length][width] := ROAD
..... end
..... gene[length][11] := ROCK
..... if length % 10 == 5 then
........ gene[length][Random(1, 10)] := FUEL
..... end
.. end
end

코드를 보면 아시겠지만, 최초의 돌길은 양쪽 가장자리를 막고 있는 장애물 외에는 아무런 장애물도 없이 일정 거리마다 연료통만이 흩어져 있는 '가장 쉬운 돌길'들입니다.

미리 말씀드리지만, 유전자알고리즘을 사용하다 보면 유전자알고리즘으로 만들어진 녀석들이 상당히 '얍삽'하다고 느낄 때가 있습니다. 이 문제에서도 알 수 있지만, 결국 '규칙'을 잘 만들지 않으면 이상한 행동을 할 때가 있습니다(사실 그 녀석들도 주어진 규칙 안에서 최대 적응도를 찾은 것이니 뭐라고 할 수도 없죠).

잘못된 높임말

이 책상은 부드러운 아이보리 색상이셔서 눈에 부담을 안주시구요, 또한 인체공학적으로 설계하셨기 때문에 인체에 부담을 안주세요. 그리고 이렇게 넓으셔서 책이나 연필이 떨어지시지도 않으시구요, 아주 인기있는 상품이세요. 마침 지금은 행사기간이시기 때문에 15% 할인해 주실 수 있으세요.

얼마전 백화점 점원에게서 들은 말입니다. 듣고 있으니 높임말을 하는 건지 아닌 건지...
명사에 붙이는 높임말은 단순히 '님'자를 붙이면 되니까 어렵지 않습니다. 서술어에 붙이는 높임말 역시 기본적으로 어렵지는 않죠. 바로 서술어를 높이면 주어가 올라간다는 원칙만 알면 말입니다.
'아이보리 색상이셔서'의 주어는 '책상'이죠. 결국 손님을 높이는 것이 아니라 책상을 높여줍니다. '부담을 안 주시구요' 역시 주어는 책상이죠. '설계하셨기'의 주어는 손님이 아니라 설계자입니다. 그 후에도 계속 책상, 책, 연필, 행사기간을 높일 뿐입니다. 심지어 '할인해 주실 수 있으세요'의 주어는 점원 자신입니다. 윗 말은 높임말인 것 같지만 실제로는 높임말이 아니죠. 정말로 높임말을 쓰려면 다음과 같이 해야겠죠.

이 책상은 부드러운 아이보리 색상이어서 눈에 부담을 안 주구요, 또한 인체공학적으로 설계했기 때문에 인체에 부담을 안줍니다. 그리고 이렇게 넓어서 책이나 연필이 떨어지지도 않구요, 아주 인기있는 상품이예요. 마침 지금은 행사기간이기 때문에 15% 할인해 드릴 수 있어요.

문제는 이렇게 하면 '뭔 점원이 높임말도 안쓰냐'라고 불평하는 '정신상 초딩'들이 많다는 것...

GA - CNNC를 이용한 XOR 회로[6] - 결과

10. 결과
다음은 앞에서 설명한 대로 CNNC신경망을 XOR회로에 맞추어 진화시킨 결과입니다.

Generation : 0
Spec[0] Node[3] Pop[512] Min[198.476] Max[405.106]

Generation : 1
Spec[0] Node[3] Pop[512] Min[207.359] Max[639.097]
Generation : 2
Spec[0] Node[3] Pop[512] Min[170.006] Max[799.999]
......
Generation : 282
Spec[0] Node[3] Pop[512] Min[250] Max[880]
Generation : 283
Spec[0] Node[3] Pop[512] Min[410] Max[860]

Generation : 284
Spec[0] Node[3] Pop[511] Min[250] Max[860]
Spec[1] Node[4] Pop[1] Min[430] Max[430]
Generation : 285
Spec[0] Node[3] Pop[273] Min[320] Max[850]
Spec[1] Node[4] Pop[239] Min[330] Max[650]
Generation : 286
Spec[0] Node[3] Pop[204] Min[440] Max[880]
Spec[1] Node[4] Pop[308] Min[360] Max[780]

Generation : 287
Spec[0] Node[3] Pop[161] Min[400] Max[860]
Spec[1] Node[4] Pop[350] Min[270] Max[800]
Spec[2] Node[5] Pop[1] Min[590] Max[590]
Generation : 288
Spec[0] Node[3] Pop[124] Min[380] Max[850]
Spec[1] Node[4] Pop[265] Min[390] Max[770]
Spec[2] Node[5] Pop[123] Min[250] Max[810]
......

Generation : 307
Spec[0] Node[3] Pop[39] Min[390] Max[830]
Spec[1] Node[4] Pop[228] Min[210] Max[970]
Spec[2] Node[5] Pop[245] Min[200] Max[950]
Generation : 308
Spec[0] Node[3] Pop[36] Min[380] Max[800]
Spec[1] Node[4] Pop[235] Min[220] Max[900]
Spec[2] Node[5] Pop[241] Min[170] Max[1000]

Generation : 309
Spec[0] Node[3] Pop[29] Min[250] Max[800]
Spec[1] Node[4] Pop[228] Min[200] Max[940]
Spec[2] Node[5] Pop[255] Min[200] Max[1000]

각각 앞에서부터 종 ID, 노드 갯수, 각 종의 개체수, 각 세대,종에 따른 최소, 최대 적응도를 의미합니다. 308세대 이후에야 겨우 최고 적응도 1000을 달성했습니다.
그런데... 일반적으로 XOR게이트는 노드 4개로도 달성 가능합니다. 그런데 5개짜리가 만들어졌군요. 적응도에 노드 갯수가 포함되어 있지 않기 때문입니다. 최소한의 노드 수, 그리고 최소한의 연결 갯수를 알기 위해서는 노드 수와 연결 수도 적응도에 포함시켜야 합니다.

여기서 주의할 점은, 가장 작은 신경망을 만들기 위해 노드 수와 연결 수에 지나치게 큰 가중치를 준다면, 유전자알고리즘은 정답률을 희생하고 크기를 줄이는 경우도 생길 수 있다는 점입니다.
그러므로, 100회의 적응도 테스트가 끝난 후 (노드 수 + 연결 수)를 적응도에서 빼는 방식을 사용했습니다.
다음은 노드와 연결 갯수까지 적응도에 적용시켜 실행한 결과입니다. seed를 바꾸어 가며 여러번 실행시킨 결과 중 가장 빨리 수렴된 결과입니다.

Generation : 0
Spec[0] Node[3] Pop[512] Min[191.699] Max[446.516]
Generation : 1
Spec[0] Node[3] Pop[512] Min[203.907] Max[660.462]
Generation : 2
Spec[0] Node[3] Pop[512] Min[205] Max[790.834]
Generation : 3
Spec[0] Node[3] Pop[512] Min[105] Max[825]
Generation : 4
Spec[0] Node[3] Pop[512] Min[195] Max[825]
Generation : 5
Spec[0] Node[3] Pop[512] Min[145] Max[825]
Generation : 6
Spec[0] Node[3] Pop[512] Min[215] Max[855]
Generation : 7
Spec[0] Node[3] Pop[512] Min[155] Max[855]
Generation : 8
Spec[0] Node[3] Pop[512] Min[195] Max[825]
Generation : 9
Spec[0] Node[3] Pop[512] Min[135] Max[845]
Generation : 10
Spec[0] Node[3] Pop[512] Min[215] Max[835]
Generation : 11
Spec[0] Node[3] Pop[512] Min[195] Max[845]
Generation : 12
Spec[0] Node[3] Pop[512] Min[255] Max[855]
Generation : 13
Spec[0] Node[3] Pop[511] Min[265] Max[905]
Spec[1] Node[4] Pop[1] Min[372] Max[372]
Generation : 14
Spec[0] Node[3] Pop[361] Min[135] Max[835]
Spec[1] Node[4] Pop[151] Min[402] Max[812]
Generation : 15
Spec[0] Node[3] Pop[287] Min[215] Max[894]
Spec[1] Node[4] Pop[225] Min[370.891] Max[872]
Generation : 16
Spec[0] Node[3] Pop[252] Min[246.175] Max[845]
Spec[1] Node[4] Pop[260] Min[232.093] Max[862]
Generation : 17
Spec[0] Node[3] Pop[218] Min[336] Max[855]
Spec[1] Node[4] Pop[294] Min[192] Max[991]
Generation : 18
Spec[0] Node[3] Pop[210] Min[175] Max[855]
Spec[1] Node[4] Pop[302] Min[234.32] Max[991]
Generation : 19
Spec[0] Node[3] Pop[216] Min[263] Max[865]
Spec[1] Node[4] Pop[296] Min[260] Max[991]

불과 17세대만에 최적화된 XOR회로가 만들어졌군요. XOR회로는 4개의 노드(세포)와 5개의 연결이 필요하니, 1000 - (4 + 5) = 991이 가장 최적화된 적응도값입니다.
유전자를 분석해서 최적화된 신경망을 그려 보았습니다. 선에 달린 숫자는 각 연결선의 강도, 세포에 달린 숫자는 각각 Bias, SigmoidFactor값입니다.

GA - CNNC를 이용한 XOR 회로[5] - 종(種) 분류 및 보호, 재생산

7. 종 분류
다른 GA에서도 마찬가지지만, CNNC 역시 다양성 확보를 위해 종을 분류하여 관리하는 것이 좋습니다.
종 분류 방법이야 많이 있지만, 여기 CNNC에서는 노드 수(세포 수)를 기준으로 종을 관리하기로 했습니다. 앞의 교차부분에서 언급했던 것처럼 노드 수가 다를 경우에는 교배가 불가능하니까 말입니다.

8. 종 보호
다양성을 위해 종별로 나누고 다양성을 유지시키기 위해 소수종을 보호합니다. 그런데 약간의 문제가 생기는군요.
기존에 소수종을 보호하기 위한 방법은, 각 개체의 적응도에 그 개체가 소속된 종의 개체수에 따라 감소시키는 것이었습니다.
문제는 개체수가 줄어들었을때 그 개체의 적응도가 증가하고, 그 개체가 선택될 가능성이 늘어남에 따라, 한번 만들어진 종은 사라질 가능성이 줄어들게 된다는 점입니다.

Node[3] Pop[28]
Node[4] Pop[34]
Node[5] Pop[37]
Node[6] Pop[23]
Node[7] Pop[31]
Node[8] Pop[34]
Node[9] Pop[19]
Node[10] Pop[33]
Node[11] Pop[37]
Node[12] Pop[28]
Node[13] Pop[37]
Node[14] Pop[31]
Node[15] Pop[24]
Node[16] Pop[31]
Node[17] Pop[39]
Node[18] Pop[33]
Node[19] Pop[13]

과 같은 결과가 나올 수도 있습니다. 더구나 같은 종 안에서만 교배해야 하는 CNNC의 특성상20~40개의 개체수 안에서 유전자알고리즘을 돌려야 한다는 이야기가 되는 것입니다(한마디로 다양성이 너무 증가되었다는 말이 되는군요).
그러므로 CNNC에서는 '소수종의 보호'가 아니라 '각 종의 보호시간'을 도입하기로 했습니다. 돌연변이에 의해 하나의 새로운 종이 새로 나타났을 경우 30세대동안 보호(다음 세대 번식때 일정비율 그 종에서 번식시킴)시키는 개념입니다. 만약 30세대동안 최적값을 못찾았다면 그 종은 아무런 보호 없이 다른 종과의 생존경쟁으로 내몰리는 것이죠.
그러므로 여기서는 종의 개체수에 따른 적응도 보정은 사용하지 않습니다.

9. 재생산
지금까지의 재생산프로세스는 거의 동일했고 단지 문제에 따라 교차 및 돌연변이만 달랐었습니다. 그러나 이 경우에는 일반적인 재생산 프로시저를 사용할 수 없습니다.
CNNC용 재생산 프로시저는 다음과 같습니다. 참고로, 재생산 대상 선택은 각 개체의 적응도를 10~100 사이로 재계산한 후 룰렛을 돌리는 재계산법을 사용했으며, 상위 16개의 개체를 그대로 복사하는 Elitism을 사용했습니다(전체 개체수는 512).

function SelectParent(CreatureList parentlist, int spe)
.. // 점수의 상한선과 하한선 찾기
.. minscore := 10000;
.. maxscore := 0;
.. for k := 0, 512 do
..... if parentlist[k].Species == spe then
........ if minscore > parentlist[k].Score then
........... minscore := parentlist[k].Score
........ end
........ if parentlist[k].Score > maxscore then
........... maxscore := parentlist[k].Score
........ end
..... end
.. end

.. if maxscore != minscore then // 모든 개체의 점수가 다 같은 경우는 적용할 수 없음
..... // max를 1000, min을 10으로 맞춤
..... newmax := 1000
..... newmin := 10
..... diff := maxscore - minscore; // 보정 전의 스코어 차이
..... for k := 0, 128 do
........ if parentlist[k].Species == spe then
........... score := parentlist[k].Score
........... score := score - minscore
........... score := score * (newmax - newmin) / diff + newmin
........... parentlist[k].TempScore := score
....... else
........... parentlist[k].TempScore := 0
........ end
..... end
.. end
.. // 이후는 Roulette법과 동일(단 Score대신 TempScore 사용)
end


procedure Regeneration(CreatureList parentlist)
.. Declear CreatureList nextgen // 다음 세대를 임시로 저장할 버퍼

.. // 16개체 엘리트 적용
.. sort(parentlist) // parentlist를 적응도순으로 정렬
.. for i := 0, 16 do
..... nextgen.Insert(parentlist[i]);
.. end

.. // parent의 종 분류
.. for spe := 0, SpeciesManager.size do
..... SpeciesManager[spe].population := 0
.. end
.. for i := 0, 512 do
..... spe := parentlist[i].size // 각 개체의 크기(노드 갯수)가 곧 종 핸들
..... parentlist[i].species := spe;
..... if spe > SpeciesManager.size then // 처음 만들어진 종이라면
........ SpeciesManager.NewSpecies() // 새로운 종 등록
........ SpeciesManager[spe].population := 1
........ SpeciesManager[spe].Species := spe
........ SpeciesManager[spe].prevent := 30
..... else
........ SpeciesManager[spe].population := SpeciesManager[spe].population + 1
..... end
.. end

.. // 보호해야 할 종 확인 - 각 종마다 남아있는 prevent값 누적
.. totalprevent := 0
.. for spe := 0, SpeciesManager.size do
..... if SpeciesManager[spe].population > 0 then
........ totalprevent := totalprevent + SpeciesManager[spe].prevent
........ SpeciesManager[spe].prevent := SpeciesManager[spe].prevent - 1
..... end
.. end

.. // 전체 개체수의 절반(256)을 보호종을 위해 할당하고,
.. // 각 종의 prevent 비율로 할당
.. Declear CreatureList malelist // 보호종의 수컷(?)들만을 모아놓을 버퍼
.. for spe := 0, SpeciesManager.size do
..... if SpeciesManager[spe].population > 0 then
........ regennum := SpeciesManager[spe].prevent * 512 / (totalprevent * 2)
........ for k := 0, regennum do
........... // spe 중에서 적응도 재계산 순서로 선택
........... selectedmale := ParentSelect(parentlist, spe);
........... malelist.Insert(selectedmale)
........ end
..... end
.. end

.. // 보호종의 암컷(?)을 찾아 교배시킴
.. for k := 0, malelist.Size do
..... spe := malelist[k].Species
..... // parentlist에서 spe를 적응도순서로 골라냄
..... female := ParentSelect(parentlist, spe);
..... // malelist[k]와 female로 새로운 개체 만듦
..... CrossOver(malelist[k], female, child)
..... nextgen.Insert(child);
.. end

.. // 나머지 갯수 채움
.. while nextgen.Size != 512 do
..... male := ParentSelect(parentlist); // 종구분없이 골라냄
..... female := ParentSelect(parentlist, male.
Species); // 같은 종에서

..... // male과 female로 새로운 개체 만듦
..... CrossOver(male, female, child)
..... nextgen.Insert(child);
.. end
.. parentlist := nextgen // 새로운 세대로 교체
end

GA - CNNC를 이용한 XOR 회로[4] - 돌연변이

6. 돌연변이
교차에 의해 만들어진 아기CNNC는 약간의 돌연변이 처치를 받습니다.
교차는 아무리 많이 하더라도 구조(라기보다는 히든노드 수)를 바꿀 수 없습니다. 그때문에 돌연변이가 필수인 것이죠.

돌연변이의 역할은 다음과 같습니다.

① 작은 돌연변이
이것은 구조를 바꾸기보다는 복제 후 각 노드의 상수(Bias, SigmoidFactor) 및 각 채널의 강도에 약간의 변경을 가합니다. 때로는 활성화되어 있던 채널을 닫거나 닫혀있던 채널을 열기도 합니다. 즉, 노드(세포) 갯수는 고정된 상태에서 새로운 연결을 만들거나 연결을 제거하는 역할을 합니다.
미소돌연변이는 큰 변이 없이 최적의 상수값을 찾아가기 위해 사용합니다.

procedure MicroMutantation(GeneNode node)
.. if MutantRate() then
..... node.Bias := Random(-5, 5)
.. else
..... node.Bias := node.Bias * Random(0.8, 1.2)
.. end

.. if MutantRate() then
..... node.SigmoidFactor := Random(-5, 5)
.. else
..... node.SigmoidFactor := node.SigmoidFactor * Random(0.8, 1.2)
.. end

.. for c := 0, gene.ChannelSize do
..... if node.RecvChannel[c] == 0 then
........ if MutantRate() then
.......... node.RecvChannel[c] := Random(-5, 5)
........ end
..... else
........ if MutantRate() then
.......... node.RecvChannel[c] := 0
........ else
.......... node.RecvChannel[c] := node.RecvChannel[c] * * Random(0.8, 1.2)
........ end
..... end
..... // SendChannel에 대해서도 동일한 처리
.. end
end

② 큰 돌연변이
거대돌연변이는 새로운 노드를 추가 또는 삭제하여 전혀 새로운 구조를 만들기 위해 사용됩니다.

procedure NodeAppend(Gene gene)
.. // 각 파라미터 초기화
.. newnode.Layer := Random(0, 1)
.. newnode.Bias := Random(-5, 5)
.. newnode.Sigmoid := Random(-5, 5)
.. //채널 초기화
.. for k := 0, ChannelSize do
..... newnode.RecvChannel[k] := 0
..... newnode.SendChannel[k] := 0
.. end

.. // 입력노드 연결
.. inputnode := NodeFind(gene, -100, 100)
..... // 모든 노드들(input node + hidden node + output node) 중에서 임의선택
.. channel := Random(0, ChannelSize)
.. newnode.RecvChannel[channel] := Random(-5, 5)
.. if inputnode.SendChannel[channel] == 0 then
..... inputnode.SendChannel[channel] := Random(-5, 5)
.. end

.. // 출력노드 연결
.. outputnode := NodeFind(gene, -100, 1)
..... // Layer가 0 이상(hidden node + output node) 인 것들 중에서 임의선택
.. channel := Random(0, ChannelSize)
.. newnode.SendChannel[channel] := Random(-5, 5)
.. if outputnode.RecvChannel[channel] == 0 then
..... outputnode.RecvChannel[channel] := Random(-5, 5)
.. end
.. gene.Insert(newnode)
end

procedure NodeRemove(Gene gene)
.. node := NodeFind(gene, 0, 1)
......... // Layer가 0과 1 사이(히든노드들) 중 임의의 노드 하나 선택
.. if node != NULL then
..... gene.Remove(node)
// 제거할 히든노드가 있을 경우에만 삭제
.. end
end

그러므로 돌연변이 루틴은 다음과 같습니다.

procedure Mutantation(Gene gene)
.. // 작은돌연변이
.. for node := 0, NodeSize do
..... MicroMutantation(gene.Node[node])
.. end

.. // 큰돌연변이
.. if MutantRate() then
..... NodeAppend(gene)
.. else if MutantRate() then
..... NodeRemove(gene)
.. end
end

GA - CNNC를 이용한 XOR 회로[3] - 교차

5. 교차
재생산에 대해 말하기 전에 먼저 교차를 어떻게 해야 할지 생각해 봅시다.
다음 두 유전자를 보죠. 보기이므로 간단하게 만들어 보았습니다.

+1.1/1/2(0000000000000000)(0010000100000000)
-0.1/1/2(0010000000000000)(0000000000000000)
-0.2/1/2(0000000100000000)(0000000000000000)

+1.1/3/4(0000000000000000)(0000001000000100)
-0.1/3/4(0000000000000100)(0000000000000000)
-0.2/3/4(0000001000000000)(0000000000000000)

둘 다 기본적인 OR회로와 같은 형태를 가지고 있습니다. 이 둘을 교차시키면 최소한 동일한 OR회로가 나와야 할 것 같습니다.
① 먼저 저 유전자를 단순한 1차원 유전자라 간주하고 1점교차를 시도해 보겠습니다.

+1.1/1/2(0000000000000000)(0010000100000000)
-0.1/1/2(0010000
000000100)(0000000000000000)
-0.2/3/4(0000001000000000)(0000000000000000)


+1.1/3/4(0000000000000000)(0000001000000100)
-0.1/3/4(0000000
000000000)(0000000000000000)
-0.2/1/2(0000000100000000)(0000000000000000)


이것으로 신경망을 만들어보면 알 수 있겠지만, 앞쪽것은 입력노드와 출력노드를 연결하던 연결 하나가 사라지고 말았습니다. 뒷쪽것은 아예 연결이 모두 사라졌네요. 결국 다음과 같이 망가진 두개의 신경망이 생기고 말았습니다.

② 그렇다면 저 3개의 노드를 한묶음으로 생각하고 교차를 해 봅시다.

+1.1/1/2(0000000000000000)(0010001000000100)
-0.1/1/2(0010000000000000)(000
0000000000000)
-0.2/1/2(0000000100000000)(000
0000000000000)

+1.1/3/4(0000000000000000)(000
0000100000000)
-0.1/3/4(0000000000000100)(000
0000000000000)
-0.2/3/4(0000001000000000)(000
0000000000000)

마찬가지 결과입니다. 윗그림과 똑같이 망가진 신경망 두개가 생기는군요.

③ 잘 생각해 보면 하나의 연결에 영향을 미치는 것은 송신채널과 수신채널에 나뉘어져 있습니다. 그렇다면 송신채널과 수신채널을 겹쳐놓고 교차시키는 것이 나을 수도 있겠군요.

+1.1/1/2(0000000000000000)
........(0010000100000100)
-0.1/1/2(0010000000000100)
........(0000000000000000)
-0.2/1/2(0000000100000000)
........(0000000000000000)

+1.1/3/4(0000000000000000)
........(0000001000000000)
-0.1/3/4(0000000000000000)
........(0000000000000000)
-0.2/3/4(0000001000000000)
........(0000000000000000)

이 경우에는 두번째 것은 연결 하나가 끊어졌지만 첫번째 것은 온전하게 남아 있습니다. 다른 교차법에 비해 그나마 낫군요.
하지만 또한가지 문제가 있습니다. 다음 두 유전자는 어떻게 교차를 시킬 수 있을까요?

+1.1/1/2(0000000000000000)(0011000100000000)
+0.7/1/2(0001000000000000)(0000000000000100)
-0.1/1/2(0010000000000100)(0000000000000000)
-0.2/1/2(0000000100000000)(0000000000000000)

+1.1/3/4(0000000000000000)(0000001000000100)
-0.1/3/4(0000000000000100)(0000000000000000)
-0.2/3/4(0000001000000000)(0000000000000000)

이 둘을 교차시키기는 쉽지 않습니다. 그러므로 CNNC에서의 교차는 '노드 수가 같을 경우에만' 하는 것으로 규정합니다.

지금까지 만들었던 유전자 알고리즘에서, 교차는 다음과 같은 방식으로 해 왔습니다.

① 두 부모 유전자의 복제를 만든다.
② 만들어진 복제의 유전자를 교차시켜 자식유전자로 한다.

즉 두 부모 유전자로부터 두 자녀유전자가 생겼습니다.
그러나 CNNC에서는 교차를 하더라도 하나는 망가지는 경우가 종종 생깁니다. 그러므로 CNNC에서는 방법을 바꾸어 두 부모유전자를 섞어 하나의 자식유전자를 만들게 됩니다.
이때는 각종 인수들(Bias, SigmoidFacter 등) 및 채널정보를 두 부모유전자의 적응도비율에 의해 부모 양쪽에서 가져옵니다. 이때 1점교차가 아니라 랜덤교차를 사용합니다.
만약 한쪽 적응도가 100, 다른쪽이 50이라면 대략 다음과 같은 자식이 나옵니다.

+1.1/3/2(0000000000000000)
........(0000001000000100)
-0.1/1/2(0000000000000100)
........(0000000000000000)
-0.2/1/2(0000001000000000)
........(0000000000000000)

물론 이 방식도 랜덤함수에 의해 잘못된 자식이 나올 가능성도 배제할 수는 없습니다만, 정상적인(그리고 보다 우수한) 자손이 나올 가능성이 더 크며 잘못된 자식은 다음 세대에 도태되므로 큰 문제를 일으키지는 않습니다(물론 알고리즘의 효율성이 조금 떨어질 수는 있죠).

procedure CrossOver(Gene male, Gene female, Gene child)
.. if male.NodeSize != female.NodeSize then // 궁합이 안맞음(노드수가 다름)
..... child.Valid := false
..... return
.. end

.. // 각 부모를 layer순으로 정렬(입력노드와 출력노드가 교차되지 않도록)
.. sort(male)
.. sort(female)

.. TotalFitness := male.Fitness + female.Fitness
.. MalePriority := male.Fitness / TotalFitness

.. // 각종 파라미터 나누기
.. for k := 0, male.NodeSize do
..... if MalePriority > Random(0, 1) then
........ child.Node[k].Layer = male.Node[k].Layer
..... else
........ child.Node[k].Layer = female.Node[k].Layer
..... end
..... // 생략, Bias와 SigmoidFactor도 동일하게 복사
.. end

.. // 채널 복사
.. for c := 0, 16 do
..... rnd := Random(0, 1)
..... for k := 0, male.NodeSize do
........ if MalePriority > rnd then
........... child.Node[k].SendChannel[c] := male.Node[k].SendChannel[c]
........... child.Node[k].RecvChannel[c] := male.Node[k].RecvChannel[c]
........ else
........... child.Node[k].SendChannel[c] := female.Node[k].SendChannel[c]
........... child.Node[k].RecvChannel[c] := female.Node[k].RecvChannel[c]
........ end
..... end
.. end
.. child.Valid := true
end

GA - CNNC를 이용한 XOR 회로[2] - 유전자 설계

3. 유전자설계
신경망에서 하나의 노드에 필요한 정보는 다음과 같습니다.
① 입력스트림 : 입력노드들과 그 노드와의 연결 강도. float형의 벡터이며 그 크기로 연결강도를 표시합니다. 이 XOR회로에서는 16개의 채널을 준비합니다.
② Layer : 노드를 구분하기 위해 사용. Layer가 0보다 작으면 입력노드, 1보다 크면 출력노드, 그 사이면 은닉노드
③ Bias : 입력스트림의 하나로 만들 수도 있지만 여기서는 노드가 따로 가지고 있음
④ SigmoidFactor : 입력의 합을 출력으로 계산할때 시그모이드 팩터를 사용
XOR회로의 경우 하나의 CNNC는 2개의 입력노드, 1개의 출력노드(그 외에 몇개가 될지 모르는 은닉노드)로 구성됩니다. 초기상태에는 은닉노드가 없으므로 CNNC 하나의 유전자는

+1.1/Bias/SF(ABCDEFGHIJKLMNOP)(abcdefghijklmnop)
-0.1/Bias/SF(ABCDEFGHIJKLMNOP)(abcdefghijklmnop)
-0.2/Bias/SF(ABCDEFGHIJKLMNOP)(abcdefghijklmnop)

과 같습니다. 이 경우 Bias, SF(SigmoidFactor), A~P, a~p는 모두 float형입니다. 가장 앞의 숫자는 Layer이며 0 이하는 입력노드, 1 이상은 출력노드를 의미합니다. 뒤의 A~P, a~p의 리스트는 각각 송신채널, 수신채널입니다. 이 값이 0이면 그 채널로 송신/수신을 않는다는뜻이며 0이 아니라면 그 채널로 송수신을 한다는 뜻입니다.

procedure InitGene(Gene gene)
.. // 3개의 노드를 만듦
.. InitNode(gene.Node[0], -0.2)

.. InitNode(gene.Node[1], -0.1)
.. InitNode(gene.Node[2], 1.1)

.. // 입력과 출력노드 사이에 초기링크 만들기
.. MakeLink(gene.Node[0], gene.Node[2])
.. MakeLink(gene.Node[1], gene.Node[2])
end


procedure InitNode(Node node, double layer)
.. node.Layer = layer
.. node.Bias = Random(-5, 5)
.. node.SigmoidFactor = Random(0.001, 3)
.. for k := 0, 16 do
..... node.SendChannel[k] := 0
..... node.RecvChannel[k] := 0

.. end
end

procedure MakeLink(Node from, Node to)
.. channel := Random(0, 15)
.. from.SendChannel[channel] := Random(-5, 5)

.. to.RecvChannel[channel] := Random(-5, 5)
end

4. 발생(Ontogeny)
개념상으로는 앞에서 말한대로 채널을 통한 노드들간의 채널통신으로 이해했지만, 실제 적용하기 위해서는 기존의 신경망방식으로 바꾸는 것이 좋습니다. 즉 송신채널과 수신채널이 일치하는 노드들끼리 연결을 만드는 것입니다.
만약 두 노드의 송신채널과 수신채널이 동시에 0이 아닐 경우 두 노드 사이에는 연결이 생깁니다. 이 연결의 크기는 송신채널의 값과 수신채널의 값에 의해 결정됩니다.
아무리 송신채널이 강하게 송신해도(송신채널의 값이 커도) 수신채널에서 약하게 수신한다면(수신채널의 값이 작으면) 두 노드 사이의 연결강도는 약해집니다. 반대로 수신채널의 값이 커도 송신을 약하게 한다면(송신채널의 값이 작으면) 마찬가지로 연결은 약해지죠.
여기서는 두 채널값으로 연결의 강도를 계산하는 공식으로 기하평균을 사용했습니다. 기하평균은 다음과 같이 계산됩니다.



procedure Ontogeny(Gene gene, Brain brain)
.. // 각 노드에 해당하는 세포를 만듦
.. for k := 0, gene.NodeNumber do

..... brain.Cell[k].Layer := gene.Node[k].Layer
..... brain.Cell[k].Bias := gene.Node[k].Bias
..... brain.Cell[k].SigmoidFactor := gene.Node[k].SigmoidFactor
.. end

.. // 각 세포들 연결
.. for k := 0, brain.CellNumber do

..... for m := 0, brain.CellNumber do
........ // 링크정보를 알기 위해 brain.Cell[k,m]에 해당하는 노드를 찾음
........ nodek := FindNode(gene, brain.Cell[k])
........ nodem := FindNode(gene, brain.Cell[m])

........ // k와 m이 얼마만큼의 세기로 연결되어 있는지 확인
........ weigth = 0;
........ for c := 0, 16 do
........... mult := nodek.SendChannel[c] * nodem.RecvChannel[c]
........... if mult != 0 then
.............. gioavg := sqrt(mult)
// 기하평균 계산
.............. weigth := weigth + gioavg
........... end

........ end
..... MakeLink(brain.Cell[k], brain.Cell[m], weigth)

..... // k->m으로 강도 weigth의 입력 만듦
.. end
end

5. 적응도 계산
위에서 만들어진 brain을 가지고 적응도를 계산합니다. 자세한 알고리즘은 생략하겠지만, 입력셀에 랜덤으로 0/1을 넣고 신경망을 돌려 나온 값과 XOR계산값을 비교하여 그 차이가 작을수록 해당 CNNC의 적응도를 높이는 방식입니다. 임의의 입력값으로 100회를 반복한 후 결과를 최종 적응도로 결정했습니다.

단, 이때 출력에 따른 적응도함수를 다음과 같이 한다면 어떨까요?

.. output := think(a, b)
.. correct = a ^ b
.. if abs(correct - output) > 0.5 the
n
..... AddFitness(0)
.. else

..... AddFitness(10)
.. end


이 방식의 가장 큰 문제점은, 참값과의 차이가 0.51인(보다 적은 변이로 참값으로 갈 수 있는) 신경망과 0.9인 신경망 둘 다 적응도가 0으로써 둘 사이의 적응도 차이를 알 수 없다는 점입니다. 유전자알고리즘의 원칙인 조금이라도 더 적응도가 우수한 것을 찾을 수가 없는 것이죠. 그러므로 적응도함수는 반드시 꼭대기가 없는 경사함수가 되어야 합니다.
이 XOR 신경망에서는 다음과 같은 적응도 함수를 사용했습니다.

.. output := think(a, b)
.. correct
= a ^ b
.. diff = abs(output - correct)
.. subfit = 1 - diff // 차이가 작을수록 적응도 높아짐
.. AddFitness(subfit * subfit * 10)

그냥 subfit를 적응도로 사용해도 되지만 여기서는 참값에 가까와질수록 선택압을 높이기 위해 subfit의 제곱을 사용하여 오른쪽 그림과 같은 함수가 되었습니다.

각 XOR신경망에 대해 랜덤입력에 의한 적응도테스트를 100회 실시하여 그 합을 적응도로 간주, 재생산을 실시합니다.

GA - CNNC를 이용한 XOR 회로[1] - 소개

1. 개요

일반적으로 신경망이라면 각 신경세포들과, 그 신경세포들 사이를 연결하는 신경섬유로 구성되어 있습니다. 신경세포는 신경섬유를 통해 연결된 다른 신경세포로부터 자극을 받아 활성화되며, 또한 신경섬유를 통해 다른 신경세포를 자극함으로써 신호가 전달됩니다.

CNNC(Cluster of Neuron Network by Channeling)는 개념적으로는 신경세포는 있지만 신경섬유는 없는 구조입니다. CNNC의 신경세포들은 신경섬유를 통해서가 아니라 특정한 채널을 통해 자신의 활성화 정도를 송신합니다. 만약 다른 신경세포가 그 채널을 통해 수신을 하고 있다면 그 세포들은 신경섬유에 의해 연결된 것으로 간주할 수 있습니다.
만약 8개의 채널을 가진 5개의 신경세포가 다음과 같은 채널을 통해 송수신하고 있다면(붉은색은 활성화, 회색은 비활성화),

신경세포
송신채널
수신채널

0123456701234567

0123456701234567

0123456701234567

0123456701234567

0123456701234567

에서 0번채널로 송신한 내용은 에서 0번채널로 수신합니다(즉 , 의 연결이 존재합니다). 그러나 에서 2번 채널로 송신한 것은 받아들이는 신경세포가 없으므로 사라집니다. 마찬가지로 에서 수신하는 4번채널 역시 송신하는 세포가 없으므로 비활성이나 마찬가지입니다. 결국 위와 같은 CNNC는 다음과 같은 신경망과 동일합니다

2. XOR 회로
아시다시피 XOR게이트는 두개의 입력을 받아 왼쪽과 같은 출력을 보이는 회로입니다. 신경망으로 OR나 AND 게이트를 만드는 것은 쉽지만, XOR게이트를 만드는 것은 약간 복잡합니다. OR과 AND는 입력층과 출력층만으로 쉽게 만들 수 있지만 XOR게이트는 중간의 은닉층이 필요하기(신경망의 구조 자체가 달라져야 하기) 때문입니다.
CNNC가 XOR회로를 만들었다고 제대로된 신경망 진화 알고리즘이라고 할 수 없지만, XOR회로를 못만든다면 CNNC는 제대로된 신경망 진화 알고리즘이라고 할 수 없죠.
그러므로 CNNC의 첫 도전으로 XOR 회로를 만들어보기로 하겠습니다.

진화론 이야기 - 만약 진화론이 붕괴된다면...

저 멀리에 흰색의 조그만 무엇인가가 보입니다. 너무 멀어서 무엇인지 알 수는 없지만 그것이 도로를 따라 움직이고 있다는 것은 알 수 있습니다. 그것을 보고 진화론자들은 '저것은 차다'라는 결론을 내립니다. 그리고 저 차가 트럭인지 승용차인지를 확인하기 위해 계속 관찰을 합니다. 반면 창조론자들은 '저것은 성경에 나와 있는 대로 배다'라고 주장을 합니다. 물론 창조론자들에게는 배가 도로에 올라와 있는 문제는 중요한 것이 아닙니다. '배가 도로에 올라와 있다니 이 얼마나 놀라운 신의 섭리인가?'라는 감탄으로 충분합니다.
그런데 어느날 그 '차'가 바다 위를 달리고 있는 것이 관찰됩니다. 그렇게 된다면 '저것은 차다'라는 결론은 어쩔수 없이 폐기되어야 합니다. 그리고는 어제까지는 도로에 있다가 지금 바다에 있는 것으로 보아 '저것은 호버크래프트다'라는 새로운 결론을 내릴 것입니다.
이때쯤 되면 창조론자들은 신이 날 것입니다. '어제까지는 차라고 했다가 오늘은 호버크래프트라고? 내일 날아다니는 것이 보이면 비행기라고 하겠군ㅋㅋ, 저것은 성경에 있는 대로 배가 맞다, 멍청한 진화가설자들아...ㅋㅋㅋ'

창조론자들은, 진화론의 설명이 매번 바뀌기 때문에 믿을 수 없는 것이라고 비난하곤 합니다. 내일 새로운 사실이 발견되면 수정될 것이라고 말입니다. 물론 새로운 발견으로 기존 이론이 수정되는 것은 과학에서는 흔한 일입니다. 하지만 그것은 수정이라기보다는 확장이라고 하는 편이 낫겠군요.

원자에서 전자가 분리될 수 있다는 것, 그리고 그 전자는 항상 일정량의 전하를 가지고 있다는 것이 발견된 후 나타난 최초의 원자모형은 왼쪽 그림과 같은 톰슨모델입니다. +전하를 띈 원자에 -전하의 전자가 건포도처럼 박혀있는 모습으로, 여기서 전자가 빠져나가면 이온이 되는 현상을 설명할 수 있습니다.
하지만 각종 원자에서 보이는 선스펙트럼 현상과 러더포드의 α선 산란 실험 등은 이와 같은 모델로는 설명이 불가능했습니다. 그래서 새로 나온 모델이 오른쪽 그림과 같은 보어모델입니다.
여기서 중요한 것은, 보어모델은 (그동안 톰슨모델로 설명할 수 있었던) 전자의 전하문제와, (톰슨모델로 설명할 수 없었던) 선스펙트럼 현상을 모두 설명할 수 있었다는 점입니다. 만약 보어모델이 선스펙트럼 현상만 설명했다면, 그리고 톰슨모델로 설명할 수 있었던 전자의 전하문제는 설명할 수 없었다면 받아들여지지 않았을 것입니다.
마찬가지로 최근의 원자모형인 궤도함수이론은 그동안 톰슨과 보어모델로 설명할 수 있었던 모든 것과 함께 그것들로 설명할 수 없었던 새로운 현상까지 모두 설명 가능했기에 받아들여질 수 있었던 것입니다.





지금이라도 진화론과 배치되는 상황이 발견된다면 진화론이 아닌 새로운 이론이 만들어질 것입니다. 그러나 그 새로운 이론은 현재까지 진화론으로 설명 가능했던 모든 이론을 포함하는 확장된 이론이 되어야 합니다. 현재까지 아무것도 설명하지 못하는 창조론이 될 수는 없는 것입니다.

창조론자들은 불만이겠지만, 그때 가서도 창조론자들의 '저것은 배다'라는 주장은 받아들여지지 않을 것입니다. 창조론자들의 주장은 어제까지 그 '배'가 땅에서 달리던 모습을 설명할 수 없기 때문입니다. 그때 가서도 창조론자들이 할 수 있는 것은 오로지 '저것은 호버크래프트다'라는 주장에 딴지를 거는 것 뿐일 것입니다.

창조론 이야기 - 확률계산

창조론자들이 좋아하는 것 중에 확률계산이 있습니다. 단백질이 만들어질 확률을 계산한 후 '봐라, 생물체가 만들어질 확률은 이렇게 작다'고 하는 것이죠.

***********************************************

옛날 학교다닐때 기숙사에서 가끔씩 친구들과 포커판을 벌이곤 했습니다. 기껏해야 100~200원씩 배팅하는 것이었지만 말이죠. 선배들중 하나는 금요일 강의 끝난 직후 시작해서 월요일 아침에 끝내고 곧장 강의실로 갔다는 전설도 전해지곤 했습니다.
어느 포커판에서 영화같은 일이 벌어졌습니다. 판돈이 한없이 올라가더니...
'자, 여기 2 포카드'
'그래? 난 7 포카드다'
'잠깐, 난 10 포카드'

여러가지 포커 룰에 따라 달라지기는 하지만, 기본적인 Five Card의 경우 세사람 다 포카드가 나올 확률은 약 2.97×10-11, 즉 0.00000000297%에 불과합니다.

극히 작은 확률이라구요?

3000명의 사람이 1000개의 자리에서 포커를 친다면 어떨까요? 그 1000개의 자리 중에서 한 자리라도 세 포카드가 동시에 나올 확률은 다음과 같이 계산됩니다.

㉠ 한 자리에서 3개의 포카드가 나오지 않을 확률 = 1 - 2.97×10-11
㉡ 1000개 자리 모두 3개의 포카드가 나오지 않을 확률 = (1 - 2.97×10-11)1000

그러므로 ㉡의 반대확률이 1000개 자리 중에서 하나라도 3개의 포카드가 나올 확률입니다. 즉

1 - (1 - 2.97×10-11)1000 ≒ 2.97×10-8 = 0.00000297%


아직 충분히 작은 확률인가요? 그렇다면 이 3000명의 사람들이 계속 포커를 한다고 쳐 봅시다(할일없는 사람들만을 모아서요^^);
만약 이들이 1000개의 자리에서 포커 10000판을 계속 친다면, 그 10000판 가운데 3개의 포카드가 나올 확률은 비슷하게 계산할 수 있습니다.

㉠ 1000개의 자리에서 세개의 포카드가 나오지 않을 확률 = 1 - 2.97×10-8
㉡ 10000판 계속할 동안 3개의 포카드가 한번도 나오지 않을 확률 = (1 - 2.97×10-8)10000

마찬가지로 ㉡의 반대확률이 1000개의 자리에서 포커를 10000번 반복할때 어느 판의 어느 자리에서든지 3개의 포카드가 나올 확률입니다.

1 - (1 - 2.97×10-8)10000 ≒ 2.97×10-4 = 0.0297%

이런 식으로 해서 1000개의 자리에서 54071750회를 반복하면 세 개의 포카드가 동시에 나올 확률은 80%를 넘게 됩니다. 한판 하는데 10분이 걸린다면, 3천명이 약 1028.8년 가까이 먹지도 자지도 않고 포커만 한다면 말입니다.

**************************************

위에서 언급한 창조론자들의 주장도 마찬가지입니다. 무엇보다 저 확률계산은 '현재의 단백질이 합성될 확률'이지, 화학진화론에서 말하는 '최초의 극히 간단한 분자형태의 생물체'를 말하는 것은 아닙니다. 현대의 화학진화론에서는 이 확률을 약 2.33×10-41로 계산하고 있습니다.
게다가 위의 포커 문제에서도 볼 수 있듯이 확률이란 확률 하나로 끝나는 것이 아니라 '그 일을 하는 개체수', 그리고 '그 일을 계속하는 시간'까지 계산해야 합니다.
위 포커의 보기에서 3000명이 1000여년동안 포커를 함으로써 포카드 세개가 한꺼번에 나올 확률은 0.00000000297%에서 80%로 늘어났습니다. 마찬가지로 바다에 녹아 있는 막대한 양의 유기물들과 10억년동안 계속되는 화학반응을 생각하면 저 2.33×10-41의 확률도얼마든지 늘어날 수 있습니다.

뱀발 : 위 포커의 보기에서 10포카드로 2와 7 포카드를 이긴 사람이 접니다...^^;

진화론 이야기 - '진화론'과 '다윈의 진화론'

진화론에 대해 창조론자들, 그리고 일부 일반인들이 쉽게 하는 착각이 있습니다. 바로 진화론은 다윈 것이라는 착각이죠.
그때문에 창조론계에서는 열심히 다윈다윈의 진화론을 깎아내리기 위해 혈안이 되어 있습니다.

다윈 대 하나님
150년 후에도 화석들은 여전히 다윈을 지지하지 않고 있다.

한때는 다윈이 죽기 전에 진화론을 부정했다는 주장까지 하더니(다행히 이 주장은 창조과학회에서 스스로 접었더군요.) 심지어는 다윈을 정신이상자로 모는 인신공격에 가까운 주장까지 하고 있습니다.

창조론은 증거에 의존하고 있는 것이 아니라 전적으로 야훼의 권위에 의존하고 있습니다. 만약 야훼의 권위가 무너지면 창조론의 권위는 사라집니다.
마찬가지로 창조론자들은 진화론 역시 다윈의 권위에 의존한다고 생각하고 있는 것입니다. 그러므로 다윈의 권위를 훼손함으로써 진화론의 권위를 떨어뜨리겠다는 생각이죠.

*****************************************

찰스 다윈이라는 사람이 어느 곳에 조그만 오두막을 세웠습니다.
며칠후 누군가가 벽을 조금 확장했습니다.
또 며칠후 다른 사람이 굴뚝을 부수고 좀더 높은 굴뚝을 세웠습니다.
또 며칠후 또다른 사람이 문짝을 떼어내고 좀더 큰 문짝으로 바꾸어 달았습니다.
....
이런 일이 반복되어 지금은 찰스 다윈이 최초에 세웠던 오두막은 흔적도 없이 사라지고 그 자리에는 커다란 벽돌집이 서 있습니다. 그런데 이 벽돌집을 '다윈의 오두막'이라 부를 수 있을까요?

현대의 진화론이 이런 모습입니다. 수많은 생물학자들이 '다윈의 진화론'에서 틀린 부분을 고치고 모자란 부분을 채워넣어 계속 진화론을 보완한 것입니다. 그 결과 현재는 '다윈의 진화론'과는 전혀 다른 모습으로, '다윈의 진화론'과는 비교도 안되게 튼튼한 '진화론'이 만들어진 것입니다.

'다윈의 진화론'은 이미 폐기되었고 새로운 진화론은 다윈의 손을 떠났습니다. 현재의 진화론은 '다윈의 진화론'이 아닌 수많은 생물학자들의 진화론입니다. 그러므로 만약 창조론계의 주장대로 다윈이 정신병자였고 죽기 전에 진화론을 부정한 것이 사실이라고 해도 진화론의 권위에는 전혀 손상이 없습니다.

창조론자들은 이점을 이해하지 못하고 지금까지도 계속 '다윈의 진화론'만을 공격하고 있습니다.

창조론 이야기 - 악마의 다리

유럽에 보면 '악마의 다리'라는 것이 종종 있습니다. 깊은 골짜기를 가로질러 놓인 다리는 사람이 놓기에는 불가능하고 악마가 놓은 다리라는 것이죠. 그에 따라 여러가지 이야기가 전해지곤 합니다

http://blog.daum.net/hangwon4/4430933


'어떤 사람이 악마와 계약 - 이 계곡을 가로지르는 다리를 놓아준다면, 그 다리를 최초로 건너는 영혼을 주겠다 - 을 했다. 그 악마는 계약대로 하룻밤만에 다리를 만들었다. 그런데 그 사람은 개 한마리를 앞세우고 최초로 다리를 건넜다. 결국 악마는 개의 영혼만을 가지고 지옥으로 돌아갔다'
'매일 계곡을 건너야 했던 여인이, 누가 이곳에 다리를 놓아준다면 영혼이라도 팔겠다고 소리쳤다. 그 이야기를 들은 악마가 하룻밤사이에 다리를 놓겠다고 장담했다. 악마가 밤새 다리를 놓는 동안 그녀는 성모 마리아에게 기도를 하였으며, 결국 악마가 마지막 돌을 놓으려고 할때 태양이 솟아올랐다.'

하지만 실상 그 다리들은 로마시대 로마인들이 세운 다리(정확히는 수도교)입니다. 로마시대에는 보통으로 할 수 있었던 일이 중세시대에는 악마밖에 못할 일이 되어버렸습니다.

***************************************************

로마의 콘스탄티누스황제가 황권의 강화를 위해 허용한 기독교(가톨릭)가 유럽의 중심사상이 되면서 모든 것의 앞에 신학을 앞세우는 풍조가 시작되었습니다. 유럽 중세 암흑기의 시작이었죠.

중세 암흑기의 가장 큰 희생양은 천문학이었습니다.
이미 2천년전 그리스인들은 지구가 둥글다는 사실을 알고 있었고, 지구의 크기를 거의 정확하게 계산까지 했습니다.
그러나 중세시대 들어와서 성경에 '땅은 평평하며 해와 달이 하늘에 붙어 돌고 있다'고 나와 있기에 둥근지구론이나 지동설은 교단의 핍박을 받아야 했습니다. 이러한 풍조는 르네상스가 시작될 때까지 계속되었죠. 그동안 과학기술과 함께 사람들 생활은 정체되어 있었습니다.

****************************************************

지금도 마찬가지일듯 싶습니다. 중세시대 '성경에 의해 '평평한 지구론'과 '천동설'을 외치던 종교인들이 지금은 '창조론', '지적설계론'을 외치고 있으니 말입니다. 만약 그들대로의 세상이 된다면...

가장 먼저 모든 생물은 야훼가 한번에 만들었으므로 그동안 눈에 가시였던 진화생물학이 초토화되겠요.
지구나이 6000년이므로 지층나이가 수억년임을 암시하는 방사성원소를 다루는 핵물리학이 된서리를 맞을 것입니다.
마찬가지로 몇만년, 몇십만년 전의 유물을 연구하는 고고학계도 철퇴를 맞겠습니다.
우주나이 역시 10000년에 불과하므로 10000광년 너머를 보려는 천문학도 찬밥이 되겠죠.
노아의 홍수도 사실이므로 지층에서 홍수흔적을 찾을 수 없는 지질학도 개밥에 도토리...

그리고 다음과 같은 말들이 나오겠죠.
'인간이 달에 가는 것이 어떻게 가능하겠냐? 옛날 달에 갔다는 사람들은 악마와의 계약에 의해 갔다 온 것이다. 어떤 사람이 자기 일행을 달로 보내주면, 달에서 죽는 최초의 영혼을 바치는 대신 다른 영혼들은 지구로 되돌려보내기로 계약을 했다. 그런데 그는 몰래 쥐 한마리를 데리고 가서 달에서 죽였지. 결국 악마는 쥐의 영혼만을 가지고 다른 사람들은 지구로 돌려보냈단다.'

진화론 이야기 - 기생충

기생충이라고 하면 대부분 회충이나 촌충 등만을 떠올리는 사람이 많습니다. 물론 이들도 기생충에 틀림없지만, 진화론에서 기생충이라면 더 넓은 범위, 즉 숙주의 자원을 빼앗아 살아가는 모든 생물을 통칭합니다. 그에 따르면 회충이나 촌충뿐 아니라 숙주에 감염해서 살아가는 박테리아나 바이러스, 벼룩, 이, 빈대 같은 생물들 역시 기생충으로 분류할 수 있습니다.

그렇다면 가장 성공적인 기생충은 무엇일까요? 가장 강한 기생충이 가장 성공적인 기생충일까요?

에볼라바이러스(Ebola Virus)를 생각해 봅시다. 더스틴호프만 주연의 '아웃브레이크'에서 한국 선박이 미국에 퍼뜨린 바이러스죠.
아시다시피 바이러스는 숙주에 감염되면 그 숙주세포의 복제장치를 사용하여 자기 자신을 복제합니다. 그 이후 그 세포를 파괴하고 나가 다른 세포에 감염되는 형태로 숙주의 몸 전체로 퍼져나갑니다. 에볼라바이러스는 그중에서도 치사율 90%에 가까운 강한(독한?) 바이러스라 할 수 있습니다. 인간에게 감염되면 불과 며칠만에 발병하여 숙주의 모든 세포가 에볼라바이러스공장으로 바뀝니다.
이 에볼라바이러스에 감염된 숙주(사람)는 며칠만에 죽게 됩니다. 그렇게 되면 그 숙주에 기생하고 있던 에볼라바이러스 역시 전멸을 피할 수 없게 됩니다. 이 에볼라바이러스의 강력함이 오히려 독으로 작용한 것이죠.

이번에는 모낭충(Demodex folliculorum)을 살펴봅시다. 사람의 피부, 특히 모낭에 기생해 살면서 세포에 구멍을 뚫고 세포액을 빨아먹고 사는 기생충입니다. 거의 모든 사람에게 기생해 살고 있지만 보통 사람들은 모낭충에 감염된 줄조차 모르고 일생을 보내죠. 보이지도 않고 통증도 없고, 지나치게 번식했을 때 여드름 등 약간의 문제가 생긴다는 것 이외에는 거의 증상이 없으니 말입니다.
숙주(사람)에 기생한 모낭충은 그 숙주에게 특별한 사고가 없는 한 80년동안(수명이 며칠밖에 안되는 모낭충에게는 상당한 시간입니다) 태평성대(?)를 누릴 수 있습니다.(물론 이들도 지나치게 번식해서 숙주에게 피부질환을 일으키게 되면 외부에서 투입되는 약물에 의해 고난의 세월을 겪기도 합니다.)

어떻습니까? 숙주를 죽일 정도로 강한 에볼라바이러스는 아프리카에서도 일부 지역을 벗어나지 못하는 반면 숙주에게 거의 해를 끼치지 않는 모낭충은 사람이 있는 곳이면 어디든지 퍼져 있습니다. 인정사정없이 숙주에게서 자원을 빼앗아 죽음에 이르게 하고 결국 자신들마저 멸망하는 에볼라바이러스보다는 숙주에게 거의 피해를 주지 않고 같이 사는 모낭충이 더 '성공적인 기생생활'을 하고 있다고 볼 수 있습니다.
창조론자들은 늘 진화론이 피도 눈물도 없는 생존경쟁을 가르친다고 비난합니다만, '사람이 왜 돕고 살아야 하는가'에 대한 설명은 이런 식으로 진화론적으로도 가능합니다.

지구와 인간의 관계는 어떨까요? 인간이 지구에 의존해서 살고 있다는 사실을 보면 지구를 숙주, 인간들을 기생충(?)이라 볼 수 있습니다. 그렇다면 우리 인간들은 정신없이 숙주를 착취하다가 숙주의 생명과 함께 끝나는 에볼라바이러스일까요, 아니면 숙주에 피해를 주지 않고 숙주가 천명을 다할 때까지 함께 사는 모낭충일까요?

한가지 더, 겨우살이(Viscum album var. coloratum)는 다른 나무에 기생하는 나무입니다. 이 씨앗은 땅에 뿌리를 내리는 것이 아니라 숙주(다른 나무)에 뿌리를 박고 숙주가 뿌리로 흡수한 물과 유기물을 빨아먹습니다.
그러나 겨우살이는 엽록소를 가지고 있으며 자신이 광합성을 할 수 있습니다. 숙주로부터 흡수한 유기물로 광합성을 한 후 만들어진 당분의 일부를 숙주에게 돌려주기도 합니다. 이 경우에는 기생충이면서도 숙주에게 도움을 주는, 공생관계에 가까와진 상태입니다.

이렇게 하여 겨우살이는 기생자이면서도 숙주와 함께 서로 도우며 살고 있습니다.

위험한 화학물질 DHMO

- 아시는 분은 다 아시는 위험한 화학 물질, DHMO에 관련된 내용입니다.

1. 디하이드로겐모노옥사이드(DHMO)는 화학 용어로 ‘히드록실 산’이라고도 하며, 산성비의 주요 성분 중 하나이다.

2. DHMO는 토양 부식의 원인 중 하나이다.

3. DHMO는 온실 효과를 일으키며 지구온난화에 기여한다.

4. DHMO에 장기 노출시 전자 장비의 고장율이 급상승한다.

5. DHMO를 일정 양 이상 섭취할 경우 구토와 두통을 유발한다.

6. DHMO를 결정화한 뒤 피부와 접촉시키면 피부 조직에 심한 손상을 입힌다.

7. DHMO는 극소량을 섭취했을 경우에도 사망하는 경우가 종종 보고된다.

8. DHMO를 기체 상태로 흡입하였을 경우 내장에 심각한 손상을 입힐 수 있다.

9. DHMO는 말기 암 환자의 암 조직에서 대량으로 발견된다.

10. DHMO 중독자에게 제공을 중지하였을 경우, 보통 일주일 내로 극심한 고통을 느끼며 죽게 된다.

11. DHMO와 관련된 일을 하는 극비 연구 조직이 미군에 존재하며, 국방성은 그들의 존재를 부인하고 있다.

12. DHMO는 대부분의 호수와 강에서 꽤 높은 확률로 발견된다.

13. DHMO가 함유된 살충제를 뿌린 후에는 아무리 세척해도 간단히 사라지지 않는다.

14. DHMO를 어떤 사람들은 ‘보이지 않는 살인자’라고 부른다.

15. DHMO를 금지시켜야 한다고 믿는 사람들이 있다.

16. DHMO의 과도한 섭취로 인해 매년 전지구적으로 수천 명 이상의 사람들이 죽는다.

17. DHMO는 자동차의 제동 성능에 심각한 손상을 주며, 이로 인해 사망한 사람들의 보고도 종종 들려오고 있다.

- 이러한 수많은 문제점에도 불구하고 정부와 관련 기업은, 자신의 이익을 위해서 DHMO의 사용을 규제하지 않고 있다. 현재로서 DHMO는 원자력 발전소의 공업용 냉각제, 스티로폼 및 플라스틱 제조 시설, 약학과 임상 동물 실험 등에 다양하게 쓰이고 있으며 그 사용량은 시간이 지나도 전혀 줄지 않고 있다. 그럼 이런 위험한 물질에 대응하기 위한 희망은 과연 존재하지 않는 것일까?

- 그렇지 않다.

- 1989년. 미국 산타크루즈 대학의 대학생 세 명이 캠퍼스 안에서 이런 내용을 담은 전단지를 나눠주며 최초로 DHMO 반대 캠페인을 벌이기 시작했다.

- 1994년. DHMO 반대 캠페인을 벌이는 최초의 웹페이지가 만들어져 넷상에 지대한 관심을 불러일으켰다.

- 1995년. 권위 있는 과학 관련 잡지인 애널로그 매거진에 DHMO의 사용을 규제하자는 전면 광고가 실렸다.

- 1997년. 미국 아이다호주의 한 14살 소년이 50명의 급우들에게 DHMO의 해로운 점을 설명하고 투표를 실시해, 47명이 DHMO를 금지해야 한다는 데 찬성했다. 그는 같은 해 아이다호주 과학 경시대회에서 이것에 관련하여 최우수상을 받았다.

- 같은 해, 역시 DHMO에 반대하는 내용을 담은 또다른 홈페이지 www.dhmo.org가 만들어졌다.

- 2004년 3월, 캘리포니아주의 한 작은 도시에서 DHMO를 규제하는 법안이 시의회에 상정되었다. 불행히도 이는 투표에 붙여지기 전에 취소되었다.

- 2004년 4월, 서부 캐나다 고등학교 영화제에서 DHMO에 대한 설명을 듣고 그것에 반대하는 서명운동에 참가한 학생과 교수들을 다룬 다큐멘터리가 상영되어 최우수상을 수상했다.

- 같은 해, 미국 케이블 TV쇼인 Bullshit!에서 DHMO 반대 운동에 관련된 내용을 방영했다.

- 2005년, 미국의 룻거 대학에서 DHMO 반대를 위한 서명 운동이 벌어져 많은 사람들이 참여했다.

- 그럼 당신은 어떻게 해야 하는가? 아래 홈페이지에 접속해서 더 자세한 내용을 알아보라.

- http://www.dhmo.org

---------------------------------------------------
DiHydrogen MonoOxyde(DHMO)는 H2O의 학명입니다.

어려운 한자어...

* 그들은 올림픽에서는 2연패했지만 대학팀과의 친선경기에서는 5연패하고 말았다.

* 자동차의 전부를 보강하지 않으면 사고시 전부 부서질 것이다.

* 최초의 폭격에 잠이 깬 기자는 전화를 들어 전화를 최초로 알릴 수 있었다.

* 그 범인의 속뜻이 어떤지는 범인이 알 수 없을 것이다.

* 유지에 싸인 편지에는 유지사업을 유지하라는 아버지의 유지가 담겨 있었다.

* 그들은 나라를 구하겠다고 국기를 흔들고 있었지만 실제로 국기를 흔드는 것은 바로 그들이었다.

* 전기한, 전기를 쓴 작가의 전기를 보면, 그는 전기에는, 근대사회의 전기를 휩쓴 발전의 전기는 전기를 사용한 전기들의 발명이라고 주장했다고 한다.





한자어를 한자로 바꾸면 이렇게 됩니다

* 그들은 올림픽에서는 2連覇했지만 대학팀과의 친선경기에서는 5連敗하고 말았다.

* 자동의 前部를 보강하지 않으면 사고시 全部 부서질 것이다.

* 최초의 폭격에 잠이 깬 기자는 電話를 들어 戰火를 최초로 알릴 수 있었다.

* 그 犯人의 속뜻이 어떤지는 凡人이 알 수 없을 것이다.

* 油紙에 싸인 편지에는 油脂사업을 維持하라는 아버지의 遺志가 담겨 있었다.

* 그들은 나라를 구하겠다고 國旗를 흔들고 있었지만 실제로 國基를 흔드는 것은 바로 그들이었다.

* 前記한, 戰記를 쓴 작가의 傳記를 보면, 그는 前期에는, 근대사회의 全期를 휩쓴 발전의 轉機는 電氣를 사용한 電機들의 발명이라고 주장했다고 한다.


위의 보기를 보니 조금 억지스러운 말도 있고, 문맥을 통해 뜻을 알 수 있는 경우도 있군요..^^;
아무튼 많은 경우에 자주 쓰이지 않는 한자어는 한자를 같이 써주지 않는 이상은 뜻을 알기가 어려운 경우도 있습니다. 그런데도 한자어, 그것도 자주 쓰이지 않는 한자어를 자주 쓰는 신문기사를 가끔씩 보게 됩니다, 특히나 連覇와 連敗 같은 것은 스포츠신문에서 자주 보게 되는데(XX팀 3연패!!!) 기사 전체를 읽지 않는 이상은 그팀이 진것인지 이긴 것인지 알 수 없는 경우도 있더군요.
한자나 영어를 섞어써야 유식해 보인다는 생각이 아직 남아있는것 같습니다.

혹시나 이 글을 보고 '역시 우리말은 한자를 섞어 써야 해'라고 생각하는 사람이 생기지나 않을지 걱정이군요.

창조론 이야기 - 잘못된 권위에 의존

김명현 교수 동영상 모음

창조과학학회 회원이며 카이스트 교수인 김명현 교수의 동영상입니다. 모기의 입이 어떻고 박쥐의 진화가 어떻고 재미있게 강의를 하고 있습니다.
일반 사람들이 보기에는 어떨까요?
'유명한 카이스트에서 학생들을 가르치는 교수의 말이니 틀릴 리가 있겠어? 다 맞는 말이겠지...'
특히나 일반 창조론자들은 큰 감동일 겁니다.
'역시 창조론은 카이스트 교수님조차 인정한 진리임에 틀림없어. 저런 진리를 모르는 멍청한 진화가설자들ㅋㅋㅋ'

한가지 자그마한 문제점이 있긴 하지만 그것에는 아무도 신경을 안쓰더군요. 바로 김명현 교수의 전공이 재료공학이라는 점입니다.
만약 김명현교수가 재료공학에 대해 이야기를 한다면 충분히 권위를 인정해줄 생각이 있습니다만 아무래도 재료공학 교수의 생물학 이야기에는 권위를 인정하기가 힘들군요.

이것이 바로 창조과학회에서 즐겨 사용하는 잘못된 권위에 의존하는 전략입니다.
카이스트 재료공학 교수도 생물학적 진화론을 거부하고 있다
는 선전용으로 말입니다.

이러한 이야기를 어느 창조론자에게 했더니 이런 반응이 나옵니다.
'재료공학자라도 나름 과학적 사고를 하는 이과교수님의 이야기인데 넌 뭐가 잘나서 교수님을 비난하냐?'
하지만 창조론자들은 '나름 과학적 사고를 하며 곁가지로 생물학을 공부재료공학자생물학 이야기'는 신뢰하면서도 '나름 과학적 사고를 하며 평생 생물학을 공부생물학자생물학 이야기'는 무시하고 있다는 것을 모르고 있습니다. 김명현교수의 창조론 이야기는 부족한 증거를 무릅쓰고 신뢰하면서 도킨스나 굴드의 진화론 이야기는 수많은 증거를 무릅쓰고 무시하는 것 말입니다.(도킨스를 생물학자가 아니라 동물학자라는 창조론자도 있는데 동물학은 생물학에 포함됩니다. 반면 재료공학은 생물학과는 전혀 관련이 없습니다)

심지어 어떤 창조론자는 이런 말까지 하더군요.
'지금은 법학박사마저 진화론이 틀리다는 것을 알고 있습니다.'
아마 어느 법학박사가 쓴 창조론책을 보고 말하는 것 같습니다만, 좀 어이가 없습니다. 이 말이 설득력을 갖기 위해서는 모든 생물학자들이 진화론을 부정하는 상황이 되어야 합니다. 지금처럼 모든 생물학자들이 진화론을 지지하는 상황에서는 저 법학자가 뭘 모르고 있다는 소리밖에 안되죠. 그런데도 '생물학에 대한 법학자의 권위'에 매달리는 모습을 당연하게 생각하는 모양입니다.

마지막, 저 강의의 반론을 보시려면 여기를 누르세요. 생물정보학을 전공하는 박사의 글입니다.

GA - 여덟여왕문제(8-Queen's Problem)[4] - 마무리

8-Queen Problem의 최종해답은 다음과 같습니다.(출처)


보시다시피 12가지 배열이 존재합니다. 그리고 저 배열들의 회전, 거울상이동 등을 허용한다면 총 92가지 배열이 가능합니다.
앞의 문제에서 종을 판단할때 회전같은 변환은 하지 않았습니다. 그렇다면 이론적으로 92개의 종이 나와야 하겠죠.

앞의 TSP에서도 마찬가지였지만, 유전자알고리즘이라는 것이 랜덤함수에 의존하는 면이 있습니다. 답을 쉽게 찾는 대신 원하는 답을 찾기가 힘들다고나 할까요?

'답을 찾아라'같은 문제라면 유전자알고리즘이 효과적입니다.
'가능한한 많은 답을 찾아라'라는 문제도 (아쉬운 대로) 유전자알고리즘으로 찾을 수 있습니다.
'모든 답을 찾아라'라면 유전자알고리즘으로서는 무리가 따름니다. 이 문제의 경우 92개의 답을 모두 찾아도 93번째 답은 없다는 것을 유전자알고리즘으로는 알 수 없기 때문입니다.

참고로 만약 유전자알고리즘으로 가능한한 많은 답을 찾기 위해서는 다음과 같은 방식을 사용하는 것이 좋습니다.
㉠ 가능한한 개체수를 많이 만들어 실행시킵니다. 개체수가 많을수록 다양성이 커져 더 많은 답을 찾을수 있습니다.
㉡ srand로 랜덤함수를 바꾸어가며 여러번 실행시킵니다.

지적설계론은 지적설계자를 모욕하는 행위 - 팬더의 엄지

작고하신 스티브 굴드의 '팬더의 엄지'로 유명해진 팬더의 엄지 이야기입니다.
팬더의 손가락을 보면 오른쪽 그림과 같이 손가락이 여섯개임을 알 수 있습니다. 하지만 해부학적으로 봤을때 손가락은 다섯개 뿐입니다. 엄지손가락은 손의 종자골이 변형되어 튀어나온 것입니다. 이 새로운 엄지손가락 덕분에 팬더는 주식인 대나무를 손으로 잡아서 먹을 수 있는 것이죠.

하지만 여기서 한가지 의문점이 생깁니다. 만약 창조주가 팬더에게 엄지손가락을 주려고 했다면 왜 영장류와 같은 엄지손가락을 주지 않았을까요? 왜 애매한 뼈를 억지로 변형시켜, 엄지손가락이 아닌 '엄지손가락 같은' 손가락을 주었을까요?