从石头到机器学习:浅谈python与人工智能

注:此为我参加专业综合实训的报告存档。未经许可,请勿转载。

引言/INTRO


从古到今,计数计算从来都是日常生活中不可或缺的一部分。在古时候,人们最早使用的计算工具是手指和石头,但手指和石头实在太低效了。
很久之后,人们开始使用算盘,但使用时需要配合一套复杂的口诀。
18世纪末,发明蒸汽机的瓦特成功制作了第一把计算尺,极大地加快了人们的计算速度。
直到1642年,19岁的帕斯卡发明了人类有史以来第一台机械计算机——帕斯卡加法器,只能够做加法和减法。
1946年,世界上第一台计算机ENIAC诞生于美国宾夕法尼亚大学。它每秒能进行5000次加法运算,是手工计算的20万倍。
1945年6月,冯·诺依曼与戈德斯坦、勃克斯等人,为埃德瓦克方案联名发表了一篇现代电脑科学发展里程碑式的文献。人们后来把根据这一方案思想设计的机器统称为“诺依曼机”。如今的计算机,都是诺依曼结构。

同一时间,随着计算机技术的高速发展,编程语言也开始快速更迭。
1946年为ENIAC编程所使用的是穿孔卡片。这种卡片上使用的语言是只有专家才能理解的语言,与人类语言差别极大,是计算机能识别的唯一语言,人类很难理解。
计算机语言发展到第二代,出现了汇编语言。汇编语言用助记符代替了操作码,用地址符号或标号代替地址码。这样就用符号代替了机器语言的二进制码。
当计算机语言发展到第三代时,它允许用英文写计算程序,程序中的符号和算式也与日常用的数学式子相近,也包括我们所学习的python。

Python 是具有易于学习、易于阅读、易于维护、免费开源等特点,十分适合初学编程者。
Python的非常简单,要输出hello world,只需一句简单的print(‘Hello World’)即可完成。

 

伴随矩阵的求解(不使用numpy的计算函数)


引入numpy包来处理矩阵,并引入行循环与列循环。当循环到x行y列时,剔除原矩阵中的相应行列再计算所剩余矩阵的代数余子式,直到循环到最后矩阵中的最后一个元素。

import numpy as np

def adj(a): #计算矩阵的伴随矩阵函数,输入二维数组
    adj = np.zeros((len(a),len(a[0]))) #初始化伴随矩阵
    #adja = [[0 for i in range(len(a))] for i in range(len(a[0]))] #未使用numpy,弃用
    for n1 in range(len(a)): #行循环
        for n2 in range(len(a[0])): #列循环
                if ((n1+1)+(n2+1))%2 == 0: #检验下标相加是否为偶数
                    adj[n2,n1] = np.linalg.det(np.delete(np.delete(a,n2,1),n1,0)) #计算代数余子式,剔除当前元素行列然后算行列式值。
                else:
                    adj[n2,n1] = (-1) * (np.linalg.det(np.delete(np.delete(a,n2,1),n1,0))) #余子式是否为负
    return(adj)

 

求解行列式的值(不使用numpy的计算函数)


通过一个嵌套函数进行。循环阶数次并嵌套计算代数余子式。

def det(a): #计算行列式,输入二维数组
   if len(a) == 1: #是否为1阶行列式
        return a[0][0]
   else: #不是1阶行列式
        s = 0
        for i in range(len(a)): #对应阶数循环次数
            n = [[row[j] for j in range(len(a)) if j!= i] for row in a[1:]] #计算余子式
            s += ((-1)**(i%2))*a[0][i]*det(n) #嵌套并计算行列式
        return(s)

 

求矩阵的逆(不使用numpy的计算函数)


求解矩阵的逆则是求伴随矩阵和求行列式的组合,将矩阵的逆除以矩阵的行列式的值即是矩阵的逆。

import numpy as np

def adj(a): #计算矩阵的伴随矩阵函数,输入二维数组
    adj = np.zeros((len(a),len(a[0]))) #初始化伴随矩阵
    #adja = [[0 for i in range(len(a))] for i in range(len(a[0]))] #未使用numpy,弃用
    for n1 in range(len(a)): #行循环
        for n2 in range(len(a[0])): #列循环
                if ((n1+1)+(n2+1))%2 == 0: #检验下标相加是否为偶数
                    adj[n2,n1] = np.linalg.det(np.delete(np.delete(a,n2,1),n1,0)) #计算代数余子式,剔除当前元素行列然后算行列式值。
                else:
                    adj[n2,n1] = (-1) * (np.linalg.det(np.delete(np.delete(a,n2,1),n1,0))) #余子式是否为负
    return(adj)

def det(a): #计算行列式,输入二维数组
   if len(a) == 1: #是否为1阶行列式
        return a[0][0]
   else: #不是1阶行列式
        s = 0
        for i in range(len(a)): #对应阶数循环次数
            n = [[row[j] for j in range(len(a)) if j!= i] for row in a[1:]] #计算余子式
            s += ((-1)**(i%2))*a[0][i]*det(n) #嵌套并计算行列式
        return(s)

def inv(a):
    return np.true_divide(adj(a),det(a))

 

 

函数图像的绘制


使用python的matplotlib包可以很方便地绘制函数图像。

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0,1,0.01)
a = x**0.125
b = x**0.25
c = x**0.5
d = x
e = x**2
f = x**4
g = x**8
plt.plot(x,a)
plt.plot(x,b)
plt.plot(x,c)
plt.plot(x,d)
plt.plot(x,e)
plt.plot(x,f)
plt.plot(x,g)

 

SA算法


模拟退火算法是一种来源于固体退火原理的基于概率算法,利用他可以解决一些简单的最短路径问题(TSP)。模拟退火算法是启发式算法的一种,具体学习的是冶金学中金属加热-冷却的过程。由S.Kirkpatrick, C.D.Gelatt和M.P.Vecchi在1983年所发明的,V.Čern在1985年也独立发明此演算法。

模拟退火算法模拟金属退火的原理是将热力学的理论套用到统计学上,将搜寻空间内每一点想象成空气内的分子;分子的能量,就是它本身的动能;而搜寻空间内的每一点,也像空气分子一样带有“能量”,以表示该点对命题的合适程度。演算法先以搜寻空间内一个任意点作起始:每一步先选择一个“邻居”,然后再计算从现有位置到达“邻居”的概率。若概率大于给定的阈值,则跳转到“邻居”;若概率较小,则停留在原位置不动。

模拟退火是启发示算法的一种,也是一种贪心算法,但是它的搜索过程引入了随机因素。在迭代更新可行解时,以一定的概率来接受一个比当前解要差的解,因此有可能会跳出这个局部的最优解,达到全局的最优解。以下图为例,假定初始解为左边蓝色点A,模拟退火算法会快速搜索到局部最优解B,但在搜索到局部最优解后,不是就此结束,而是会以一定的概率接受到左边的移动。也许经过几次这样的不是局部最优的移动后会到达全局最优点D,于是就跳出了局部最小值。

利用SA算法求解TSP问题:

import numpy as np
import matplotlib.pyplot as plt
import math
import random
import pandas as pd
Data280 = pd.read_csv('tspa280.csv')
City = Data280.values

def main():
    route = GenerateRandomRoute(280)
    dist = getRouteDist(City[:],route)
    plotRoute(City,route)
    
    #SA algorithm
    T = 100
    alpha = 0.9
    Tmin = 1e-4
    results = []
    results.append((route,dist))
    route_best = []
    dist_best = 0;
    counter = 0
    while T>Tmin:
        route_best = route
        dist_best = dist
        flag = 0
        for i in range(5000):
            if(random.random()>0.5):
                #route_new = getNewRoute1(route[:])
                route_new = getNewRoute3(route[:],random.randint(1,10))    
            else:
                route_new = getNewRoute2(route[:])
            
            counter = counter + 1
            dist_new = getRouteDist(City[:],route_new)
            if (dist_new < dist or math.exp(-(dist_new - dist)/T)> random.random()):             
                flag = 1
                dist = dist_new
                route = route_new
                if dist小于dist_best:
                    dist_best = dist
                    route_best = route
    
        if flag:
            route = route_best
            dist = dist_best           
        
        T = T*alpha
        results.append((route_best,dist_best))
        
        if(counter%100==0):
            plt.figure
            plotRoute(City,route_best)
        
    plt.figure
    dists = [results[i][1] for i in range(len(results))]  
    plt.plot(dists)
    plt.show()
    
    plt.figure
    plotRoute(City,route_best)
  
    print("All=",counter)
    
    
def r(X1,X2):
    return np.linalg.norm(X1-X2,ord=2) 
   
    
def GenerateRandomRoute(CityNum)   :
    return random.sample(range(0,CityNum),CityNum)

def getRouteDist(City,rt):
    city_p = City[rt[0]]
    jx = [j for j in range(len(rt)) if j!=0]
    dist = 0
       
    for j in jx:
        city_n = City[rt[j]]
        dist_i = r(city_p,city_n) 
        dist = dist + dist_i    
        city_p = city_n
        
    dist = dist + r(City[rt[0]],city_p)
    return dist

def getNewRoute1(route_c):
    # randomly change the positions of two cities
    route_new = route_c
   
    return route_new    

def getNewRoute3(route_c,city_n):
    # randomly change the positions of n cities
    route_new = route_c
    
    return route_new  

def getNewRoute2(route_c):
    # reverse the cities in the two random selected cities
    route_new = route_c
    
    return route_new    


def plotRoute(City,route):
    city_p = City[route[0]]
    jx = [j for j in range(len(route)) if j!=0]
    dist = 0
    plt.figure
    
    for j in jx:
        city_n = City[route[j]]
        dist_i = r(city_p,city_n) 
        dist = dist + dist_i
        x = np.array([city_p[0],city_n[0]])
        y = np.array([city_p[1],city_n[1]])
        plt.plot(x,y)
        plt.scatter(x,y)
        
        city_p = city_n
        
    dist = dist + r(City[route[0]],city_p)
    x = np.array([city_p[0],City[route[0]][0]])
    y = np.array([city_p[1],City[route[0]][1]])
    plt.plot(x,y)
    plt.scatter(x,y)
    
    cap = "dist=%.2f"%(dist)
    plt.title(cap)
    plt.show()
    return dist    
if __name__ == '__main__':
    # for i in range(100):
    main()

TSP280.CSV:

X,Y
288,149
288,129
270,133
256,141
256,157
246,157
236,169
228,169
228,161
220,169
212,169
204,169
196,169
188,169
196,161
188,145
172,145
164,145
156,145
148,145
140,145
148,169
164,169
172,169
156,169
140,169
132,169
124,169
116,161
104,153
104,161
104,169
90,165
80,157
64,157
64,165
56,169
56,161
56,153
56,145
56,137
56,129
56,121
40,121
40,129
40,137
40,145
40,153
40,161
40,169
32,169
32,161
32,153
32,145
32,137
32,129
32,121
32,113
40,113
56,113
56,105
48,99
40,99
32,97
32,89
24,89
16,97
16,109
8,109
8,97
8,89
8,81
8,73
8,65
8,57
16,57
8,49
8,41
24,45
32,41
32,49
32,57
32,65
32,73
32,81
40,83
40,73
40,63
40,51
44,43
44,35
44,27
32,25
24,25
16,25
16,17
24,17
32,17
44,11
56,9
56,17
56,25
56,33
56,41
64,41
72,41
72,49
56,49
48,51
56,57
56,65
48,63
48,73
56,73
56,81
48,83
56,89
56,97
104,97
104,105
104,113
104,121
104,129
104,137
104,145
116,145
124,145
132,145
132,137
140,137
148,137
156,137
164,137
172,125
172,117
172,109
172,101
172,93
172,85
180,85
180,77
180,69
180,61
180,53
172,53
172,61
172,69
172,77
164,81
148,85
124,85
124,93
124,109
124,125
124,117
124,101
104,89
104,81
104,73
104,65
104,49
104,41
104,33
104,25
104,17
92,9
80,9
72,9
64,21
72,25
80,25
80,25
80,41
88,49
104,57
124,69
124,77
132,81
140,65
132,61
124,61
124,53
124,45
124,37
124,29
132,21
124,21
120,9
128,9
136,9
148,9
162,9
156,25
172,21
180,21
180,29
172,29
172,37
172,45
180,45
180,37
188,41
196,49
204,57
212,65
220,73
228,69
228,77
236,77
236,69
236,61
228,61
228,53
236,53
236,45
228,45
228,37
236,37
236,29
228,29
228,21
236,21
252,21
260,29
260,37
260,45
260,53
260,61
260,69
260,77
276,77
276,69
276,61
276,53
284,53
284,61
284,69
284,77
284,85
284,93
284,101
288,109
280,109
276,101
276,93
276,85
268,97
260,109
252,101
260,93
260,85
236,85
228,85
228,93
236,93
236,101
228,101
228,109
228,117
228,125
220,125
212,117
204,109
196,101
188,93
180,93
180,101
180,109
180,117
180,125
196,145
204,145
212,145
220,145
228,145
236,145
246,141
252,125
260,129
280,133

 

GA算法


最早由美国人John holland于20世纪70年代提出,该算法是根据大自然中生物体进化规律而设计提出的。是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法。

该算法通过数学的方式,利用计算机仿真运算,将问题的求解过程转换成类似生物进化中的染色体基因的交叉、变异等过程。

在求解较为复杂的组合优化问题时,相对一些常规的优化算法,GA算法通常能够较快地获得较好的优化结果。遗传算法已被人们广泛地应用于组合优化、机器学习、信号处理、自适应控制和人工生命等领域。

遗传算法的基本运算过程如下:

(1)初始化:设置进化代数计数器t=0,设置最大进化代数T,随机生成M个个体作为初始群体P(0)。(2)个体评价:计算群体P(t)中各个个体的适应度。(3)选择运算:将选择算子作用于群体。选择的目的是把优化的个体直接遗传到下一代或通过配对交叉产生新的个体再遗传到下一代。选择操作是建立在群体中个体的适应度评估基础上的。(4)交叉运算:将交叉算子作用于群体。遗传算法中起核心作用的就是交叉算子。(5)变异运算:将变异算子作用于群体。即是对群体中的个体串的某些基因座上的基因值作变动。群体P(t)经过选择、交叉、变异运算之后得到下一代群体P(t+1)。(6)终止条件判断:若t=T,则以进化过程中所得到的具有最大适应度个体作为最优解输出,终止计算。

遗传操作包括以下三个基本遗传算子:选择、交叉、变异。

用GA算法求解TSP问题:

import numpy as np
import matplotlib.pyplot as plt
import math
import random
 
city_name=[]
city_condition=[]

with open('tspa280.csv', 'rb') as f:
    lines=f.readlines()
    for line in lines:
        line=line.decode().strip().split('\n')[0]
        line=line.split(',')
        city_name.append(line[0])
        city_condition.append([float(lines[1]),float(lines[2])])
city_condition=np.array(city_condition)
 
city_count=len(city_name)
Distance=np.zeros([city_count,city_count])
for i in range(city_count):
    for j in range(city_count):
        Distance[i][j]=math.sqrt((city_condition[i][0]-city_condition[j][0])**2+(city_condition[i][1]-city_condition[j][1])**2)
count=300
improve_count=30000
itter_time=30000
retain_rate=0.2
random_select_rate=0.5
mutation_rate=0.1
origin=15
index=[i for i in range(city_count)]
index.remove(15)

def get_total_distance(x):
    distance=0
    distance+=Distance[origin][x[0]]
    for i in range(len(x)):
        if i==len(x)-1:
            distance += Distance[origin][x[i]]
        else:
            distance += Distance[x[i]][x[i+1]]
    return distance
 
def improve(x):
    i=0
    distance=get_total_distance(x)
    while i小于improve_count:
        u=random.randint(0,len(x)-1)
        v = random.randint(0, len(x)-1)
        if u!=v:
            new_x=x.copy()
            t=new_x[u]
            new_x[u]=new_x[v]
            new_x[v]=t
            new_distance=get_total_distance(new_x)
            if new_distance小于distance:
                distance=new_distance
                x=new_x.copy()
        else:
            continue
        i+=1
 
def selection(population):
    graded = [[get_total_distance(x), x] for x in population]
    graded = [x[1] for x in sorted(graded)]
    retain_length = int(len(graded) * retain_rate)
    parents = graded[:retain_length]
    for chromosome in graded[retain_length:]:
        if random.random() 小于 random_select_rate:
            parents.append(chromosome)
    return parents
 
def crossover(parents):
    target_count=count-len(parents)
    children=[]
    while len(children)小于target_count:
        male_index = random.randint(0, len(parents) - 1)
        female_index = random.randint(0, len(parents) - 1)
        if male_index!=female_index:
            male=parents[male_index]
            female=parents[female_index]
 
            left=random.randint(0,len(male)-2)
            right=random.randint(left+1,len(male)-1)
            gene1=male[left:right]
            gene2=female[left:right]
            child1_c=male[right:]+male[:right]
            child2_c=female[right:]+female[:right]
            child1=child1_c.copy()
            child2= child2_c.copy()
            for o in gene2:
                child1_c.remove(o)
            for o in gene1:
                child2_c.remove(o)
            child1[left:right]=gene2
            child2[left:right]=gene1
            child1[right:]=child1_c[0:len(child1)-right]
            child1[:left] = child1_c[len(child1) - right:]
            child2[right:] = child2_c[0:len(child1) - right]
            child2[:left] = child2_c[len(child1) - right:]
            children.append(child1)
            children.append(child2)
    return children
 
def mutation(children):
    for i in range(len(children)):
        if random.random() 小于 mutation_rate:
            child=children[i]
            u=random.randint(1,len(child)-4)
            v = random.randint(u+1, len(child)-3)
            w= random.randint(v+1, len(child)-2)
            child=children[i]
            child=child[0:u]+child[v:w]+child[u:v]+child[w:]
 
def get_result(population):
    graded = [[get_total_distance(x), x] for x in population]
    graded = sorted(graded)
    return graded[0][0],graded[0][1]
 
population=[]
for i in range(count):
    x=index.copy()
    random.shuffle(x)
    improve(x)
    population.append(x)
 
register=[]
i=0
distance, result_path = get_result(population)
while i小于itter_time:
    parents=selection(population)
    children=crossover(parents)
    mutation(children)
    population=parents+children
    distance,result_path=get_result(population)
    register.append(distance)
    i=i+1
    
print(distance)
print(result_path)
 
result_path=[origin]+result_path+[origin]
X=[]
Y=[]
for index in result_path:
    X.append(city_condition[index,0])
    Y.append(city_condition[index, 1])
 
plt.plot(X,Y,'-o')
plt.show()
ti = "最佳距离 =%.2f"% (distance)
plt.title(ti)
plt.plot(list(range(len(register))),register)
plt.show()

 

BP神经网络


BP(back propagation)神经网络是1986年由Rumelhart和McClelland为首的科学家提出的概念,是一种按照误差逆向传播算法训练的多层前馈神经网络,是应用最广泛的神经网络。

人工神经网络无需事先确定输入输出之间映射关系的数学方程,仅通过自身的训练,学习某种规则,在给定输入值时得到最接近期望输出值的结果。作为一种智能信息处理系统,人工神经网络实现其功能的核心是算法。BP神经网络是一种按误差反向传播(简称误差反传)训练的多层前馈网络,其算法称为BP算法,它的基本思想是梯度下降法,利用梯度搜索技术,以期使网络的实际输出值和期望输出值的误差均方差为最小。

基本BP算法包括信号的前向传播和误差的反向传播两个过程。即计算误差输出时按从输入到输出的方向进行,而调整权值和阈值则从输出到输入的方向进行。正向传播时,输入信号通过隐含层作用于输出节点,经过非线性变换,产生输出信号,若实际输出与期望输出不相符,则转入误差的反向传播过程。误差反传是将输出误差通过隐含层向输入层逐层反传,并将误差分摊给各层所有单元,以从各层获得的误差信号作为调整各单元权值的依据。通过调整输入节点与隐层节点的联接强度和隐层节点与输出节点的联接强度以及阈值,使误差沿梯度方向下降,经过反复学习训练,确定与最小误差相对应的网络参数(权值和阈值),训练即告停止。此时经过训练的神经网络即能对类似样本的输入信息,自行处理输出误差最小的经过非线形转换的信息。

 

1、设计单层BP神经网络,推导权重和阈值的学习规则,每次学习一个样本,并编程实现逼近f(x) = sin(x)。写出权重和阈值的学习规则的推导公式。绘制误差迭代曲线。

import numpy as np
import math
import matplotlib.pyplot as plt

x = np.linspace(-3,3,600)
x_size = x.size
y = np.zeros((x_size,1))
# print(y.size)
for i in range(x_size):
    #y[i]= math.sin(x[i])**2
    #y[i] = x[i]*2 + 1
    #y[i] = (np.exp(x[i])-np.exp(-x[i]))/2
    #y[i] = -5*np.exp(-x[i]**2-x[i]*3+5)*np.sin(x[i]+1)
    #y[i]=math.sin(x[i])
    y[i]=x[i]**2-2*x[i]+1

hidesize = 2
W1 = np.random.random((hidesize,1)) #输入层与隐层之间的权重
B1 = np.random.random((hidesize,1)) #隐含层神经元的阈值
W2 = np.random.random((1,hidesize)) #隐含层与输出层之间的权重
B2 = np.random.random((1,1)) #输出层神经元的阈值
threshold = 0.0001
max_steps = 1000
def sigmoid(x_):
    y_ = 1/(1+math.exp(-x_))
    return y_

E = np.zeros((max_steps,1))#误差随迭代次数的变化
Y = np.zeros((x_size,1)) # 模型的输出结果
for k in range(max_steps):
    temp = 0
    for i in range(x_size):
        hide_in = np.dot(x[i],W1)-B1 # 隐含层输入数据
        #print(x[i])
        hide_out = np.zeros((hidesize,1)) #隐含层的输出数据
        for j in range(hidesize):
            #print("第{}个的值是{}".format(j,hide_in[j]))
            #print(j,sigmoid(j))
            hide_out[j] = sigmoid(hide_in[j])
            #print("第{}个的值是{}".format(j, hide_out[j]))

        #print(hide_out[3])
        y_out = np.dot(W2,hide_out) - B2 #模型输出

        Y[i] = y_out
        e = y_out - y[i] # 模型输出减去实际结果。得出误差
        ##反馈,修改参数
        dB2 = -1*threshold*e
        dW2 = e*threshold*np.transpose(hide_out)
        dB1 = np.zeros((hidesize,1))
        for j in range(hidesize):
            dB1[j] = np.dot(np.dot(W2[0][j],sigmoid(hide_in[j])),(1-sigmoid(hide_in[j]))*(-1)*e*threshold)

        dW1 = np.zeros((hidesize,1))

        for j in range(hidesize):
            dW1[j] = np.dot(np.dot(W2[0][j],sigmoid(hide_in[j])),(1-sigmoid(hide_in[j]))*x[i]*e*threshold)

        W1 = W1 - dW1
        B1 = B1 - dB1
        W2 = W2 - dW2
        B2 = B2 - dB2
        temp = temp + abs(e)

    E[k] = temp/x_size
    if k%100==0:
        print(k)
        
plt.plot(E)
plt.show()
        
eY = np.zeros((x_size,1))       
for i in range(x_size):
    hide_in = np.dot(x[i],W1)-B1 # 隐含层输入数据
        #print(x[i])
    hide_out = np.zeros((hidesize,1)) #隐含层的输出数据
    for j in range(hidesize):
            #print("第{}个的值是{}".format(j,hide_in[j]))
            #print(j,sigmoid(j))
        hide_out[j] = sigmoid(hide_in[j])
            #print("第{}个的值是{}".format(j, hide_out[j]))
        #print(hide_out[3])
    y_out = np.dot(W2,hide_out) - B2 #模型输出
    Y[i] = y_out
    eY[i] = y_out - y[i] 
plt.plot(y,'k.')
plt.plot(Y,'r-')
plt.plot(eY)
plt.show()

 

2、设计三层BP神经网络,推导权重和阈值的学习规则,并编程实现逼近f(x) = x^2 -2*x + 1,每次学习N个样本,写出权重和阈值的学习规则的推导公式,绘制误差迭代曲线。

import numpy as np
import matplotlib.pyplot as plt

def sigmoid(x):
    y = 1/(1+np.exp(-x))    
    return y

def dsigmoid(x):
    return sigmoid(x)*(1- sigmoid(x))
    
def myfunction(x):
    y = x**2 - x*2 + 1
    return y

#初始化NN
input_size = 1
hide_size = 30
output_size = 1

W1 = np.random.random([input_size,hide_size]) #输入层与隐层之间的权重
B1 = np.random.random([1,hide_size]) #隐含层神经元的阈值
    
W2 = np.random.random([hide_size,output_size]) #隐含层与输出层之间的权重
B2 = np.random.random([output_size,1]) #输出层神经元的阈值

#构造NN
X = np.random.random([1,input_size])

H_in = np.dot(X,W1) + B1
H_out = sigmoid(H_in)

O_in = np.dot(H_out,W2) + B2
O_out = O_in

Y = np.dot(sigmoid(np.dot(X,W1) + B1),W2) + B2

#学习
Samples = 1000
X_train = X = np.random.random([Samples,input_size])*6-2
Y_train = myfunction(X_train)

Y_NN = np.dot(sigmoid(np.dot(X_train,W1) + B1),W2) 
N = 20000
yita = 0.0001
results = []
for i in range(N):
    #X_train = X = np.random.random([Samples,input_size])*2-2
    Y_train = myfunction(X_train)
    Y_NN = np.dot(sigmoid(np.dot(X_train,W1) + B1),W2) + B2
    H_in = np.dot(X_train,W1) + B1
    H_out = sigmoid(H_in)
    
    delta = (Y_NN - Y_train)
    E = sum(delta**2)/2
    
    W2 = W2 - yita*(np.dot(H_out.T,delta))
    B2 = B2 - yita*sum(delta)   
    
    W1 = W1 - yita*(np.dot(np.dot((delta*X_train).T,dsigmoid(H_in)),W2))
    B1 = B1 - yita*(np.dot(np.dot((delta).T,dsigmoid(H_in)),W2))   
    results.append(E)
    

figure1 = plt.figure(1)
Ei = results[:][:]
plt.plot(Ei)
plt.show


figure2 = plt.figure(2)
X_train = X = np.random.random([Samples,input_size])*6-2
Y_train = myfunction(X_train)
Y_NN = np.dot(sigmoid(np.dot(X_train,W1) + B1),W2) + B2

plt.plot(X_train,Y_train,'r.')
plt.plot(X_train,Y_NN,'g.')
plt.show

 

人脸识别


import numpy as np
import cv2

# 人脸识别分类器
faceCascade = cv2.CascadeClassifier(r'C:\ProgramData\Anaconda3\Lib\site-packages\cv2\data\haarcascade_frontalface_default.xml')

# 识别眼睛的分类器
eyeCascade = cv2.CascadeClassifier(r'C:\ProgramData\Anaconda3\Lib\site-packages\cv2\data\haarcascade_eye.xml')

# 开启摄像头
cap = cv2.VideoCapture(0)
ok = True

while ok:
    # 读取摄像头中的图像,ok为是否读取成功的判断参数
    ok, img = cap.read()
    # 转换成灰度图像
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # 人脸检测
    faces = faceCascade.detectMultiScale(
        gray,     
        scaleFactor=1.2,
        minNeighbors=5,     
        minSize=(32, 32)
    )

    # 在检测人脸的基础上检测眼睛
    for (x, y, w, h) in faces:
        fac_gray = gray[y: (y+h), x: (x+w)]
        result = []
        eyes = eyeCascade.detectMultiScale(fac_gray, 1.3, 2)

        # 眼睛坐标的换算,将相对位置换成绝对位置
        for (ex, ey, ew, eh) in eyes:
            result.append((x+ex, y+ey, ew, eh))

    # 画矩形
    for (x, y, w, h) in faces:
        cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)

    for (ex, ey, ew, eh) in result:
        cv2.rectangle(img, (ex, ey), (ex+ew, ey+eh), (0, 255, 0), 2)
 
    cv2.imshow('video', img)

    k = cv2.waitKey(1)
    if k == 27:    # press 'ESC' to quit
        break
 
cap.release()
cv2.destroyAllWindows()

 

Python 编程考核:双指针法


给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

def maxArea(self, height):
        # 记录当前最大容量的面积
    max_area = 0
        # 记录最左边的下标
    left = 0
        # 记录右边的下标
    right = len(height) - 1
        # 当右边下标大于左边下标的时候循环
    while right > left:
            # 当前循环中最大的容量面积,使用max方法比较上次的max_area和此次的容量面积,取最大值
            # min(height[left], height[right]) * (right - left) 取左边和右边的高当中的最小值
            max_area = max(max_area, min(height[left], height[right]) * (right - left))
            # 判断哪条高小,小的那边下标进行操作
            if height[right] > height[left]:
                left += 1
            else:
                right -= 1
    return max_area

 

总结


作为一个简单、开源免费的高层语言,python极低的学习成本把编程带入了百姓寻常家,也使得人工智能与机器学习变得普遍开来,Python语言未来前景也是一片向好。

Python的特点是优雅简单,易学易用,最简单易懂的代码实现需要的功能。Python适宜于开发网络应用,脚本写作,日常简单小工具等等。

总的来说,python在数据科学和 AI 中占据主导地位;拥有优质的文档和丰富的库,对于科学用途的广泛编程任务都很有用;设计非常好,快速,坚固,可移植,可扩展;开源,而且拥有一个健康、活跃、支持度高的社区。

经过4周的python与人工智能专业实训令我感到受益匪浅,使我进一步了解了人工智能与机器学习的基础知识与基本技能。在这个人工智能高速发展的时代,无论是对于深入学习还是就业都是起到了极其重要的作用。

Python是一门新手友好、功能强大、高效灵活的编程语言,学会之后无论是想进入数据分析、人工智能、网站开发这些领域,还是希望掌握第一门编程语言,都可以用Python来开启未来无限可能!

 

参考


部分代码来自CSDN

点赞

发表评论

电子邮件地址不会被公开。必填项已用 * 标注