算法

遗传算法

Genetic Algorithms: An Overview

遗传算法三要素:

  1. 染色体总体
  2. 基于适应值的选择
  3. 交叉产生子代,子代的随机变异

Most methods called \GAs" have at least the following elements in common: populations of chromosomes, selection according to fitness, crossover to produce
new offspring, and random mutation of new offspring.

染色体以0 1 位字符串的形式存在,

The chromosomes in a GA population most often take the form of bit strings (i.e., strings of
1s and 0s); each bit position (\locus") in the chromosome has two possible v alues (\alleles"),
0 and 1.

适应度函数:适应度函数给当前总体中每一个染色体打分
适应度取决于染色体解决问题的能力

The GA most often requires a \¯tness function" that assigns a score (¯tness)
to each chromosome in the current population. The ¯tness of the chromosome depends on
how well that chromosome solves the problem at hand.

例如,GA用于函数优化问题时( function optimization)就是寻找能够最大化一个多元函数的变量值,下面看1维情况:
f (x) = x + |sin(32x)|
x between 0 and \(pi\)

染色体:编码为代表实数的bit字符串
适应度:将bit字符串转化为实数并evaluate函数在此点的值

Here the candidate solutions are v alues
of x, which can be encoded as bit strings representing real numbers. The ¯tness calculation
translates a given bit string into a real number x and then ev aluates the function at that
v alue. The ¯tness of a string is the function v alue at that point.

再一个例子:
机器人走迷宫
前后左右:2bit即可表示
走100步 可以用长200的字符串表示
适应度用距离出口的距离来度量,距离越小,适应度越大

最简单的ga也应包括:

  • 根据适应度的选择
  • Crossover:
    10000100 and 11111111在第三个位置交叉后变成10011111 and 11100100
  • Mutation
    就是随机反转某一位00000100 might be mutated in its second position to yield 01000100

工作流程:

  1. Start with a randomly generated population of N L-bit chromosomes (candidate solutions to a problem).
  2. Calculate the ¯tness F (x) of each chromosome x in the population.
  3. Repeat the following steps (a){(c) until N o®spring have been created:
  • 选择两个父代染色体:可以重复抽样,选择概率正比于适应度函数
    Select a pair of parent chromosomes from the current population, with the probability of selection being an increasing function of ¯tness. Selection is done \with replacement," meaning that the same chromosome can be selected more than once
    to become a parent
  • 根据交叉概率,如果有交叉,就均匀选取一个交叉点,如果没有,就直接将亲代复制形成两个和亲代一样的子代
    With probability pc (the crossover probability), cross over the pair at a randomly chosen point (chosen with uniform probability) to form two o®spring. If
    no crossover takes place, form two o®spring that are exact copies of their respective parents
  • 变异
    Mutate the two o®spring at each locus with probability pm (the mutation probability), and place the resulting chromosomes in the new population.
  1. Replace the current population with the new population.
  2. Go to step 2.

(This assumes that N is even; if N is odd, one o®spring can be discarded at random.)
每一次迭代都是一个generation,大约50到500代叫做一个run

Each iteration of this process is called a \generation." A GA is typically iterated for anywhere
from 50 to 500 or more generations, which is called a \run." At the end of a run, there are
often one or more highly ¯t chromosomes in the population. Since randomness plays a large
role in each run, two runs with di®erent random number seeds will generally produce di®erent
detailed behavior. GA researchers often report statistics (such as the best ¯tness found and
generation at which best ¯tness was found) averaged over many di®erent runs of the GA on
the same problem.

详细的例子:囚徒困境

情景描述:A和B是两个嫌疑人,被抓了

  • 合作’代表俩人之间‘合作’,即都不供出对方,这样两人各得3分
  • Defect栏代表一个人招供了,另一个没有,没招供得0分招供的那个人得了5分
  • 但是如果俩人都招供了,每人各得一分

最后谁的分数大,谁‘得利’越多,惩罚越小(实际上:分数=5-住监狱的时间)
显然最优策略是defect啊,这样最多得5分,最少得1分
有一个比赛(described in Axelrod, 1984),两个参赛队,每个队可以记住前三个回合各自出的牌,有的参赛者采用马尔可夫,贝叶斯等试图model其他player,但最后获胜的是tit for tat的策略:第一轮合作,以后每次出牌都是对手上一次出的牌。我们来看一下ga能否找出这个‘最优解’:
If C C (case 1), then C .
If C D (case 2), then D.
If DC (case 3), then C .
If DD (case 4), then D

实验1

编码:由于可以记忆前三轮的,而前三轮有444=64种可能性,故一个策略strategy可以编码为64bit的字符串,Axelrod实际使用了70bit,因为需要初始三轮的结果,故增加6bit
这样搜索空间是2的70次方啊!太大了!
(注:为什么有64种可能就要用64bit?想象一下,如果仅能记忆前一轮的结果,那么前一轮的结果有四种可能,我根据前一轮的结果决定下一轮的出牌,因此一个策略就可以表示为四位,因为一轮是两位嘛)
fitness:专家发现了已知的8个人类产生的strategy很有代表性,因此每一个个体的strategy的适应值为它与那八个值的结果的均值
GA总体:20个这种‘策略’
每一次run:50代,即每一次run总共有1000个个体,且每次的 random number seed不一样。总共40个run

结果:ga搜索到的策略分数比TIT FOR T A T. 还高,这并不意味着产生的策略比TIT FOR T A T. 好,因为fitness的时候,只与那8个做了play,也就是说产生的结果和那8个有关,即与环境有关,而TIT FOR T A T. 更general,它所在的环境更大。GA的策略利用了这8个策略的弱点。

实验2

环境变为与同一代的其他个体(还有自己)对赛

¯tness of a strategy was determined by allowing the strategies
in the population to play with e ach other rather than with the ¯xed set of eight strategies.
At every generation, each strategy played iterated games with each of
the nineteen other members of the population as well as with itself, and its ¯tness was again

结果一开始合作的都灭绝掉了,20代之后,GA发现合作的分手更高就惩罚defection的

论文最后一部分How and Why do Genetic Algorithms Work?讲解ga的工作机理,不过有点太含糊了,有一个schema的公式,没看懂,呜呜,先放一放吧,得先会用啊!

模糊推断系统FIS

http://www.dma.fi.upm.es/java/fuzzy/fuzzyinf/motiv_en.htm
这个地方讲解了一些基本知识,解释了matlab模糊工具箱自带的一个例子,根据输入变量(服务质量和food质量)的打分,决定输出变量(tip应该是小费?)的大小,这个是根据mamdani算法(妈妈打你)弄的,很不错。然后我按照matlab的工具箱做了一下

最近邻与k-d tree

来自维基:http://en.wikipedia.org/wiki/K-d_tree
要搜索训练数据集中与test point最近的点,一种是linear搜索,就是求出所有点与test point的距离,在训练集少的时候有效,大的时候就得用k-d tree了
最近邻分类的训练阶段其实就是构造k-d tree,predict阶段就是搜索树,维基上有代码和算法解释,我注释一下:

from collections import namedtuple
from operator import itemgetter
from pprint import  pformat
class Node(namedtuple('Node','location,leftChild,rightChild')):
    def __repr__(self):
        return pformat(tuple(self))
def kdTree(pointList,depth=0):
    
    try:
        k=len(pointList[0])#最后的子节点不是列表了,因此无法index
    except IndexError as e:
        return None
    #axis指定按照那个轴进行排序,然后划分
    axis=depth%k
    pointList.sort(key=itemgetter(axis))
    
    median=len(pointList)//2#整除
    return Node(
        location=pointList[median],
        leftChild=kdTree(pointList[:median],depth+1),
        rightChild=kdTree(pointList[median+1:],depth+1))
def main():
    "example usage"
    point_list = [(2,3), (5,4), (9,6), (4,7), (8,1), (7,2)]
    tree=kdTree(point_list)
    print(tree)
if __name__=='__main__':
    main()

其中

  1. namedtuple('Node','location,leftChild,rightChild')构造了一个元组tuple的子类,就是除了通常tuple的index操作又增加了新的index,类似结构体
Point = namedtuple('Point', ['x', 'y'], verbose=True)
或Point = namedtuple('Point', 'x,y', verbose=True)
就可以进行如下
p = Point(11, y=22) 
p[0] + p[1]  
x, y = p
p.x + p.y  
等操作
  1. pointList.sort(key=itemgetter(axis))
    对列表进行排序,key关键字的值是一个函数
    而itemgetter的用法近似为
def itemgetter(*items):
   return tuple(obj[item] for item in items)

例如itemgetter(1)('ABCDEFG')返回'B'
itemgetter(1,3,5)('ABCDEFG')返回('B', 'D', 'F')
3. median=len(pointList)//2#整除
4. print函数调用类的方法

def __repr__(self):
        return pformat(tuple(self))
  1. 递归
    结束条件:
try:
        k=len(pointList[0])#最后的子节点不是列表了,因此无法index
    except IndexError as e:
        return None
posted @ 2015-03-16 13:45  marquis  阅读(269)  评论(0编辑  收藏  举报