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
이상은 꿈이고, 자신감이고 우리를 앞으로 나아가게 만드는 희망입니다.
회의는 깨어 있는 것이고 의심하는 것입니다. 과학을 하는 사람들은 절대 이 말을 잊으면 안됩니다.
from : SBS Drama Kaist(마지막 강의)
GA - CNNC를 이용한 XOR 회로[3] - 교차
5. 교차
재생산에 대해 말하기 전에 먼저 교차를 어떻게 해야 할지 생각해 봅시다.
다음 두 유전자를 보죠. 보기이므로 간단하게 만들어 보았습니다.
둘 다 기본적인 OR회로와 같은 형태를 가지고 있습니다. 이 둘을 교차시키면 최소한 동일한 OR회로가 나와야 할 것 같습니다.
① 먼저 저 유전자를 단순한 1차원 유전자라 간주하고 1점교차를 시도해 보겠습니다.
이것으로 신경망을 만들어보면 알 수 있겠지만, 앞쪽것은 입력노드와 출력노드를 연결하던 연결 하나가 사라지고 말았습니다. 뒷쪽것은 아예 연결이 모두 사라졌네요. 결국 다음과 같이 망가진 두개의 신경망이 생기고 말았습니다.
② 그렇다면 저 3개의 노드를 한묶음으로 생각하고 교차를 해 봅시다.
마찬가지 결과입니다. 윗그림과 똑같이 망가진 신경망 두개가 생기는군요.
③ 잘 생각해 보면 하나의 연결에 영향을 미치는 것은 송신채널과 수신채널에 나뉘어져 있습니다. 그렇다면 송신채널과 수신채널을 겹쳐놓고 교차시키는 것이 나을 수도 있겠군요.
이 경우에는 두번째 것은 연결 하나가 끊어졌지만 첫번째 것은 온전하게 남아 있습니다. 다른 교차법에 비해 그나마 낫군요.
하지만 또한가지 문제가 있습니다. 다음 두 유전자는 어떻게 교차를 시킬 수 있을까요?
이 둘을 교차시키기는 쉽지 않습니다. 그러므로 CNNC에서의 교차는 '노드 수가 같을 경우에만' 하는 것으로 규정합니다.
지금까지 만들었던 유전자 알고리즘에서, 교차는 다음과 같은 방식으로 해 왔습니다.
① 두 부모 유전자의 복제를 만든다.
② 만들어진 복제의 유전자를 교차시켜 자식유전자로 한다.
즉 두 부모 유전자로부터 두 자녀유전자가 생겼습니다.
그러나 CNNC에서는 교차를 하더라도 하나는 망가지는 경우가 종종 생깁니다. 그러므로 CNNC에서는 방법을 바꾸어 두 부모유전자를 섞어 하나의 자식유전자를 만들게 됩니다.
이때는 각종 인수들(Bias, SigmoidFacter 등) 및 채널정보를 두 부모유전자의 적응도비율에 의해 부모 양쪽에서 가져옵니다. 이때 1점교차가 아니라 랜덤교차를 사용합니다.
만약 한쪽 적응도가 100, 다른쪽이 50이라면 대략 다음과 같은 자식이 나옵니다.
물론 이 방식도 랜덤함수에 의해 잘못된 자식이 나올 가능성도 배제할 수는 없습니다만, 정상적인(그리고 보다 우수한) 자손이 나올 가능성이 더 크며 잘못된 자식은 다음 세대에 도태되므로 큰 문제를 일으키지는 않습니다(물론 알고리즘의 효율성이 조금 떨어질 수는 있죠).
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
재생산에 대해 말하기 전에 먼저 교차를 어떻게 해야 할지 생각해 봅시다.
다음 두 유전자를 보죠. 보기이므로 간단하게 만들어 보았습니다.
+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)
-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(0010000000000100)(0000000000000000)
-0.2/3/4(0000001000000000)(0000000000000000)
+1.1/3/4(0000000000000000)(0000001000000100)
-0.1/3/4(0000000000000000)(0000000000000000)
-0.2/1/2(0000000100000000)(0000000000000000)
-0.1/1/2(0010000000000100)(0000000000000000)
-0.2/3/4(0000001000000000)(0000000000000000)
+1.1/3/4(0000000000000000)(0000001000000100)
-0.1/3/4(0000000000000000)(0000000000000000)
-0.2/1/2(0000000100000000)(0000000000000000)
이것으로 신경망을 만들어보면 알 수 있겠지만, 앞쪽것은 입력노드와 출력노드를 연결하던 연결 하나가 사라지고 말았습니다. 뒷쪽것은 아예 연결이 모두 사라졌네요. 결국 다음과 같이 망가진 두개의 신경망이 생기고 말았습니다.
② 그렇다면 저 3개의 노드를 한묶음으로 생각하고 교차를 해 봅시다.
+1.1/1/2(0000000000000000)(0010001000000100)
-0.1/1/2(0010000000000000)(0000000000000000)
-0.2/1/2(0000000100000000)(0000000000000000)
+1.1/3/4(0000000000000000)(0000000100000000)
-0.1/3/4(0000000000000100)(0000000000000000)
-0.2/3/4(0000001000000000)(0000000000000000)
-0.1/1/2(0010000000000000)(0000000000000000)
-0.2/1/2(0000000100000000)(0000000000000000)
+1.1/3/4(0000000000000000)(0000000100000000)
-0.1/3/4(0000000000000100)(0000000000000000)
-0.2/3/4(0000001000000000)(0000000000000000)
마찬가지 결과입니다. 윗그림과 똑같이 망가진 신경망 두개가 생기는군요.
③ 잘 생각해 보면 하나의 연결에 영향을 미치는 것은 송신채널과 수신채널에 나뉘어져 있습니다. 그렇다면 송신채널과 수신채널을 겹쳐놓고 교차시키는 것이 나을 수도 있겠군요.
+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)
........(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)
+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)
........(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 하나의 유전자는
과 같습니다. 이 경우 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 then
..... 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회 실시하여 그 합을 적응도로 간주, 재생산을 실시합니다.
신경망에서 하나의 노드에 필요한 정보는 다음과 같습니다.
① 입력스트림 : 입력노드들과 그 노드와의 연결 강도. 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)
-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 then
..... 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개의 신경세포가 다음과 같은 채널을 통해 송수신하고 있다면(붉은색은 활성화, 회색은 비활성화),
라에서 0번채널로 송신한 내용은 나와 다에서 0번채널로 수신합니다(즉 라와 다, 라와 나의 연결이 존재합니다). 그러나 마에서 2번 채널로 송신한 것은 받아들이는 신경세포가 없으므로 사라집니다. 마찬가지로 가에서 수신하는 4번채널 역시 송신하는 세포가 없으므로 비활성이나 마찬가지입니다. 결국 위와 같은 CNNC는 다음과 같은 신경망과 동일합니다
2. XOR 회로
아시다시피 XOR게이트는 두개의 입력을 받아 왼쪽과 같은 출력을 보이는 회로입니다. 신경망으로 OR나 AND 게이트를 만드는 것은 쉽지만, XOR게이트를 만드는 것은 약간 복잡합니다. OR과 AND는 입력층과 출력층만으로 쉽게 만들 수 있지만 XOR게이트는 중간의 은닉층이 필요하기(신경망의 구조 자체가 달라져야 하기) 때문입니다.
CNNC가 XOR회로를 만들었다고 제대로된 신경망 진화 알고리즘이라고 할 수 없지만, XOR회로를 못만든다면 CNNC는 제대로된 신경망 진화 알고리즘이라고 할 수 없죠.
그러므로 CNNC의 첫 도전으로 XOR 회로를 만들어보기로 하겠습니다.
일반적으로 신경망이라면 각 신경세포들과, 그 신경세포들 사이를 연결하는 신경섬유로 구성되어 있습니다. 신경세포는 신경섬유를 통해 연결된 다른 신경세포로부터 자극을 받아 활성화되며, 또한 신경섬유를 통해 다른 신경세포를 자극함으로써 신호가 전달됩니다.
CNNC(Cluster of Neuron Network by Channeling)는 개념적으로는 신경세포는 있지만 신경섬유는 없는 구조입니다. CNNC의 신경세포들은 신경섬유를 통해서가 아니라 특정한 채널을 통해 자신의 활성화 정도를 송신합니다. 만약 다른 신경세포가 그 채널을 통해 수신을 하고 있다면 그 세포들은 신경섬유에 의해 연결된 것으로 간주할 수 있습니다.
만약 8개의 채널을 가진 5개의 신경세포가 다음과 같은 채널을 통해 송수신하고 있다면(붉은색은 활성화, 회색은 비활성화),
신경세포 | 송신채널 | 수신채널 |
가 | 01234567 | 01234567 |
나 | 01234567 | 01234567 |
다 | 01234567 | 01234567 |
라 | 01234567 | 01234567 |
마 | 01234567 | 01234567 |
라에서 0번채널로 송신한 내용은 나와 다에서 0번채널로 수신합니다(즉 라와 다, 라와 나의 연결이 존재합니다). 그러나 마에서 2번 채널로 송신한 것은 받아들이는 신경세포가 없으므로 사라집니다. 마찬가지로 가에서 수신하는 4번채널 역시 송신하는 세포가 없으므로 비활성이나 마찬가지입니다. 결국 위와 같은 CNNC는 다음과 같은 신경망과 동일합니다
2. XOR 회로
아시다시피 XOR게이트는 두개의 입력을 받아 왼쪽과 같은 출력을 보이는 회로입니다. 신경망으로 OR나 AND 게이트를 만드는 것은 쉽지만, XOR게이트를 만드는 것은 약간 복잡합니다. OR과 AND는 입력층과 출력층만으로 쉽게 만들 수 있지만 XOR게이트는 중간의 은닉층이 필요하기(신경망의 구조 자체가 달라져야 하기) 때문입니다.
CNNC가 XOR회로를 만들었다고 제대로된 신경망 진화 알고리즘이라고 할 수 없지만, XOR회로를 못만든다면 CNNC는 제대로된 신경망 진화 알고리즘이라고 할 수 없죠.
그러므로 CNNC의 첫 도전으로 XOR 회로를 만들어보기로 하겠습니다.
진화론 이야기 - 만약 진화론이 붕괴된다면...
저 멀리에 흰색의 조그만 무엇인가가 보입니다. 너무 멀어서 무엇인지 알 수는 없지만 그것이 도로를 따라 움직이고 있다는 것은 알 수 있습니다. 그것을 보고 진화론자들은 '저것은 차다'라는 결론을 내립니다. 그리고 저 차가 트럭인지 승용차인지를 확인하기 위해 계속 관찰을 합니다. 반면 창조론자들은 '저것은 성경에 나와 있는 대로 배다'라고 주장을 합니다. 물론 창조론자들에게는 배가 도로에 올라와 있는 문제는 중요한 것이 아닙니다. '배가 도로에 올라와 있다니 이 얼마나 놀라운 신의 섭리인가?'라는 감탄으로 충분합니다.
그런데 어느날 그 '차'가 바다 위를 달리고 있는 것이 관찰됩니다. 그렇게 된다면 '저것은 차다'라는 결론은 어쩔수 없이 폐기되어야 합니다. 그리고는 어제까지는 도로에 있다가 지금 바다에 있는 것으로 보아 '저것은 호버크래프트다'라는 새로운 결론을 내릴 것입니다.
이때쯤 되면 창조론자들은 신이 날 것입니다. '어제까지는 차라고 했다가 오늘은 호버크래프트라고? 내일 날아다니는 것이 보이면 비행기라고 하겠군ㅋㅋ, 저것은 성경에 있는 대로 배가 맞다, 멍청한 진화가설자들아...ㅋㅋㅋ'
창조론자들은, 진화론의 설명이 매번 바뀌기 때문에 믿을 수 없는 것이라고 비난하곤 합니다. 내일 새로운 사실이 발견되면 수정될 것이라고 말입니다. 물론 새로운 발견으로 기존 이론이 수정되는 것은 과학에서는 흔한 일입니다. 하지만 그것은 수정이라기보다는 확장이라고 하는 편이 낫겠군요.
원자에서 전자가 분리될 수 있다는 것, 그리고 그 전자는 항상 일정량의 전하를 가지고 있다는 것이 발견된 후 나타난 최초의 원자모형은 왼쪽 그림과 같은 톰슨모델입니다. +전하를 띈 원자에 -전하의 전자가 건포도처럼 박혀있는 모습으로, 여기서 전자가 빠져나가면 이온이 되는 현상을 설명할 수 있습니다.
하지만 각종 원자에서 보이는 선스펙트럼 현상과 러더포드의 α선 산란 실험 등은 이와 같은 모델로는 설명이 불가능했습니다. 그래서 새로 나온 모델이 오른쪽 그림과 같은 보어모델입니다.
여기서 중요한 것은, 보어모델은 (그동안 톰슨모델로 설명할 수 있었던) 전자의 전하문제와, (톰슨모델로 설명할 수 없었던) 선스펙트럼 현상을 모두 설명할 수 있었다는 점입니다. 만약 보어모델이 선스펙트럼 현상만 설명했다면, 그리고 톰슨모델로 설명할 수 있었던 전자의 전하문제는 설명할 수 없었다면 받아들여지지 않았을 것입니다.
마찬가지로 최근의 원자모형인 궤도함수이론은 그동안 톰슨과 보어모델로 설명할 수 있었던 모든 것과 함께 그것들로 설명할 수 없었던 새로운 현상까지 모두 설명 가능했기에 받아들여질 수 있었던 것입니다.
지금이라도 진화론과 배치되는 상황이 발견된다면 진화론이 아닌 새로운 이론이 만들어질 것입니다. 그러나 그 새로운 이론은 현재까지 진화론으로 설명 가능했던 모든 이론을 포함하는 확장된 이론이 되어야 합니다. 현재까지 아무것도 설명하지 못하는 창조론이 될 수는 없는 것입니다.
창조론자들은 불만이겠지만, 그때 가서도 창조론자들의 '저것은 배다'라는 주장은 받아들여지지 않을 것입니다. 창조론자들의 주장은 어제까지 그 '배'가 땅에서 달리던 모습을 설명할 수 없기 때문입니다. 그때 가서도 창조론자들이 할 수 있는 것은 오로지 '저것은 호버크래프트다'라는 주장에 딴지를 거는 것 뿐일 것입니다.
그런데 어느날 그 '차'가 바다 위를 달리고 있는 것이 관찰됩니다. 그렇게 된다면 '저것은 차다'라는 결론은 어쩔수 없이 폐기되어야 합니다. 그리고는 어제까지는 도로에 있다가 지금 바다에 있는 것으로 보아 '저것은 호버크래프트다'라는 새로운 결론을 내릴 것입니다.
이때쯤 되면 창조론자들은 신이 날 것입니다. '어제까지는 차라고 했다가 오늘은 호버크래프트라고? 내일 날아다니는 것이 보이면 비행기라고 하겠군ㅋㅋ, 저것은 성경에 있는 대로 배가 맞다, 멍청한 진화가설자들아...ㅋㅋㅋ'
창조론자들은, 진화론의 설명이 매번 바뀌기 때문에 믿을 수 없는 것이라고 비난하곤 합니다. 내일 새로운 사실이 발견되면 수정될 것이라고 말입니다. 물론 새로운 발견으로 기존 이론이 수정되는 것은 과학에서는 흔한 일입니다. 하지만 그것은 수정이라기보다는 확장이라고 하는 편이 낫겠군요.
하지만 각종 원자에서 보이는 선스펙트럼 현상과 러더포드의 α선 산란 실험 등은 이와 같은 모델로는 설명이 불가능했습니다. 그래서 새로 나온 모델이 오른쪽 그림과 같은 보어모델입니다.
여기서 중요한 것은, 보어모델은 (그동안 톰슨모델로 설명할 수 있었던) 전자의 전하문제와, (톰슨모델로 설명할 수 없었던) 선스펙트럼 현상을 모두 설명할 수 있었다는 점입니다. 만약 보어모델이 선스펙트럼 현상만 설명했다면, 그리고 톰슨모델로 설명할 수 있었던 전자의 전하문제는 설명할 수 없었다면 받아들여지지 않았을 것입니다.
마찬가지로 최근의 원자모형인 궤도함수이론은 그동안 톰슨과 보어모델로 설명할 수 있었던 모든 것과 함께 그것들로 설명할 수 없었던 새로운 현상까지 모두 설명 가능했기에 받아들여질 수 있었던 것입니다.
지금이라도 진화론과 배치되는 상황이 발견된다면 진화론이 아닌 새로운 이론이 만들어질 것입니다. 그러나 그 새로운 이론은 현재까지 진화론으로 설명 가능했던 모든 이론을 포함하는 확장된 이론이 되어야 합니다. 현재까지 아무것도 설명하지 못하는 창조론이 될 수는 없는 것입니다.
창조론자들은 불만이겠지만, 그때 가서도 창조론자들의 '저것은 배다'라는 주장은 받아들여지지 않을 것입니다. 창조론자들의 주장은 어제까지 그 '배'가 땅에서 달리던 모습을 설명할 수 없기 때문입니다. 그때 가서도 창조론자들이 할 수 있는 것은 오로지 '저것은 호버크래프트다'라는 주장에 딴지를 거는 것 뿐일 것입니다.
창조론 이야기 - 확률계산
창조론자들이 좋아하는 것 중에 확률계산이 있습니다. 단백질이 만들어질 확률을 계산한 후 '봐라, 생물체가 만들어질 확률은 이렇게 작다'고 하는 것이죠.
어느 포커판에서 영화같은 일이 벌어졌습니다. 판돈이 한없이 올라가더니...
'자, 여기 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개의 포카드가 나올 확률입니다.
이런 식으로 해서 1000개의 자리에서 54071750회를 반복하면 세 개의 포카드가 동시에 나올 확률은 80%를 넘게 됩니다. 한판 하는데 10분이 걸린다면, 3천명이 약 1028.8년 가까이 먹지도 자지도 않고 포커만 한다면 말입니다.
위에서 언급한 창조론자들의 주장도 마찬가지입니다. 무엇보다 저 확률계산은 '현재의 단백질이 합성될 확률'이지, 화학진화론에서 말하는 '최초의 극히 간단한 분자형태의 생물체'를 말하는 것은 아닙니다. 현대의 화학진화론에서는 이 확률을 약 2.33×10-41로 계산하고 있습니다.
게다가 위의 포커 문제에서도 볼 수 있듯이 확률이란 확률 하나로 끝나는 것이 아니라 '그 일을 하는 개체수', 그리고 '그 일을 계속하는 시간'까지 계산해야 합니다.
위 포커의 보기에서 3000명이 1000여년동안 포커를 함으로써 포카드 세개가 한꺼번에 나올 확률은 0.00000000297%에서 80%로 늘어났습니다. 마찬가지로 바다에 녹아 있는 막대한 양의 유기물들과 10억년동안 계속되는 화학반응을 생각하면 저 2.33×10-41의 확률도얼마든지 늘어날 수 있습니다.
뱀발 : 위 포커의 보기에서 10포카드로 2와 7 포카드를 이긴 사람이 접니다...^^;
***********************************************
옛날 학교다닐때 기숙사에서 가끔씩 친구들과 포커판을 벌이곤 했습니다. 기껏해야 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년 후에도 화석들은 여전히 다윈을 지지하지 않고 있다.
한때는 다윈이 죽기 전에 진화론을 부정했다는 주장까지 하더니(다행히 이 주장은 창조과학회에서 스스로 접었더군요.) 심지어는 다윈을 정신이상자로 모는 인신공격에 가까운 주장까지 하고 있습니다.
창조론은 증거에 의존하고 있는 것이 아니라 전적으로 야훼의 권위에 의존하고 있습니다. 만약 야훼의 권위가 무너지면 창조론의 권위는 사라집니다.
마찬가지로 창조론자들은 진화론 역시 다윈의 권위에 의존한다고 생각하고 있는 것입니다. 그러므로 다윈의 권위를 훼손함으로써 진화론의 권위를 떨어뜨리겠다는 생각이죠.
찰스 다윈이라는 사람이 어느 곳에 조그만 오두막을 세웠습니다.
며칠후 누군가가 벽을 조금 확장했습니다.
또 며칠후 다른 사람이 굴뚝을 부수고 좀더 높은 굴뚝을 세웠습니다.
또 며칠후 또다른 사람이 문짝을 떼어내고 좀더 큰 문짝으로 바꾸어 달았습니다.
....
이런 일이 반복되어 지금은 찰스 다윈이 최초에 세웠던 오두막은 흔적도 없이 사라지고 그 자리에는 커다란 벽돌집이 서 있습니다. 그런데 이 벽돌집을 '다윈의 오두막'이라 부를 수 있을까요?
현대의 진화론이 이런 모습입니다. 수많은 생물학자들이 '다윈의 진화론'에서 틀린 부분을 고치고 모자란 부분을 채워넣어 계속 진화론을 보완한 것입니다. 그 결과 현재는 '다윈의 진화론'과는 전혀 다른 모습으로, '다윈의 진화론'과는 비교도 안되게 튼튼한 '진화론'이 만들어진 것입니다.
'다윈의 진화론'은 이미 폐기되었고 새로운 진화론은 다윈의 손을 떠났습니다. 현재의 진화론은 '다윈의 진화론'이 아닌 수많은 생물학자들의 진화론입니다. 그러므로 만약 창조론계의 주장대로 다윈이 정신병자였고 죽기 전에 진화론을 부정한 것이 사실이라고 해도 진화론의 권위에는 전혀 손상이 없습니다.
창조론자들은 이점을 이해하지 못하고 지금까지도 계속 '다윈의 진화론'만을 공격하고 있습니다.
그때문에 창조론계에서는 열심히 다윈과 다윈의 진화론을 깎아내리기 위해 혈안이 되어 있습니다.
다윈 대 하나님
150년 후에도 화석들은 여전히 다윈을 지지하지 않고 있다.
한때는 다윈이 죽기 전에 진화론을 부정했다는 주장까지 하더니(다행히 이 주장은 창조과학회에서 스스로 접었더군요.) 심지어는 다윈을 정신이상자로 모는 인신공격에 가까운 주장까지 하고 있습니다.
창조론은 증거에 의존하고 있는 것이 아니라 전적으로 야훼의 권위에 의존하고 있습니다. 만약 야훼의 권위가 무너지면 창조론의 권위는 사라집니다.
마찬가지로 창조론자들은 진화론 역시 다윈의 권위에 의존한다고 생각하고 있는 것입니다. 그러므로 다윈의 권위를 훼손함으로써 진화론의 권위를 떨어뜨리겠다는 생각이죠.
*****************************************
찰스 다윈이라는 사람이 어느 곳에 조그만 오두막을 세웠습니다.
며칠후 누군가가 벽을 조금 확장했습니다.
또 며칠후 다른 사람이 굴뚝을 부수고 좀더 높은 굴뚝을 세웠습니다.
또 며칠후 또다른 사람이 문짝을 떼어내고 좀더 큰 문짝으로 바꾸어 달았습니다.
....
이런 일이 반복되어 지금은 찰스 다윈이 최초에 세웠던 오두막은 흔적도 없이 사라지고 그 자리에는 커다란 벽돌집이 서 있습니다. 그런데 이 벽돌집을 '다윈의 오두막'이라 부를 수 있을까요?
현대의 진화론이 이런 모습입니다. 수많은 생물학자들이 '다윈의 진화론'에서 틀린 부분을 고치고 모자란 부분을 채워넣어 계속 진화론을 보완한 것입니다. 그 결과 현재는 '다윈의 진화론'과는 전혀 다른 모습으로, '다윈의 진화론'과는 비교도 안되게 튼튼한 '진화론'이 만들어진 것입니다.
'다윈의 진화론'은 이미 폐기되었고 새로운 진화론은 다윈의 손을 떠났습니다. 현재의 진화론은 '다윈의 진화론'이 아닌 수많은 생물학자들의 진화론입니다. 그러므로 만약 창조론계의 주장대로 다윈이 정신병자였고 죽기 전에 진화론을 부정한 것이 사실이라고 해도 진화론의 권위에는 전혀 손상이 없습니다.
창조론자들은 이점을 이해하지 못하고 지금까지도 계속 '다윈의 진화론'만을 공격하고 있습니다.
피드 구독하기:
글 (Atom)