算法
遗传算法
Genetic Algorithms: An Overview
遗传算法三要素:
- 染色体总体
- 基于适应值的选择
- 交叉产生子代,子代的随机变异
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
工作流程:
- Start with a randomly generated population of N L-bit chromosomes (candidate solutions to a problem).
- Calculate the ¯tness F (x) of each chromosome x in the population.
- 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.
- Replace the current population with the new population.
- 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()
其中
- 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
等操作
- 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))
- 递归
结束条件:
try:
k=len(pointList[0])#最后的子节点不是列表了,因此无法index
except IndexError as e:
return None