算法目录

前言
数据结构基本概念
1. 数据
数据是信息的载体,是描述客观事物属性的数,字符以及所有能输入到计算机中被程序识别和处理的符号合集
2. 数据元素
数据元素是数据的基本单位,通常作为一个整体进行处理。一个数据元素可由若干数据组成,数据项是构成数据元素不可分割的最小单位。例如,学生档案是一个数据元素,它是由学号,性别,名字等数据项组成的。
3. 数据对象
数据对象是具有相同数据元素的合集。是一个数据的子集。例如, 整数的数据对象是N={0,±1,±2,。。。}
4. 数据类型
原子类型:其值不可再分的数据类型
结构类型: 其值可以在分解为若干分量
抽象数据类型:抽象数据与之相关的操作
5. 抽象数据结构
抽象数据类型(ADT)是指一个数学模型及其定义在该模型的一系列操作。通常用数据对象,数据关系,基本操作集三元组来表示抽象数据类型。
6. 数据结构
数据之间存在相互的关系,这种关系就称为数据结构。数据机构包括三方面:逻辑结构,储存结构,数据的运算
数据结构三要素
1. 数据的逻辑结构
2. 数据的储存结构
3. 数据的运算
算法基本概念与度量
1. 基本概念
算法(Algorithm)是对特定问题求最优解的一种描述,一个算法需要具备5个重要特征:
- )有穷性。对于任何合法的输入值必须在有穷步以后结束,且每一步再有穷时间内完成
- )确定性。 保证不会出现薛定谔的量子不确定状态,即同样条件下的同一输入值得出不同的结果
- )可行性。算法描述中的操作是可以做到的,可用induction归纳法证明出来
- )输入。一个算法有零个或者多个输入,来自于某个特定的对象的合集
- )输出。一个算法有一个或多个输出,输出与输入有特定关系的量。
2. 时间复杂度
一行指令被重复的频次就是频度。Σni=1频度=T(n)
算法中的基本运算频度是f(n),算法的时间复杂度记为T(n)=O(f(n)).
Asymptotic Analysis——渐近分析

big 0 notation 三个rules
- ignore constant factor
- Combine fixed number of terms with same complexity(special case: n terms)
consider only the most higher dimension power
3. 空间复杂度
一个算法所耗费的储存空间。
记为S(n)=O(g(n))空间复杂度 O(1)
int i = 1;int j = 2;i++ ;++j;//代码中的 i、j 所分配的空间都不随着处理数据量变化,因此它的空间复杂度 S(n) = O(1)
空间复杂度 O(n) ```python a = n x = [None]*a print(x)
[None, None, None, None, None, None, None, None, None, None,。。。。]
创建了n个空间,所以占用了这么多的空间,即 S(n) = O(n)
常见的复杂度不多,从低到高排列就这么几个: O(1) 、 O(log(n)) 、 O(n) 、 O(n2)---<a name="L1QLs"></a># 线性表<a name="KKc2E"></a>## 数组<a name="k42Tp"></a>## 链表---<a name="x2QQ4"></a># 散列表---<a name="C8hUj"></a># 树---<a name="EMw87"></a># 图---<a name="VjIC4"></a># 复杂度分析---<a name="y8JxZ"></a># 基本算法思路---<a name="YMbqw"></a># 排序---<a name="Sy28m"></a># 搜索---<a name="gbybK"></a># 查找---<a name="E1FG1"></a># 字符串匹配---<a name="w0ByP"></a># 不精确一维搜索-Armijo-Goldstein准则与Wolfe-Powell准则(ama505)不精确一维搜索就是在区间【0,∞)上求近似最小值,用一个可以接受的参数来表示这个近似值,使用条件是函数 f ′ ( 0 ) < 0。<br />主要有两种方法:Armijo-Goldstein法和Wolfe-Powell法**Armijo-Goldstein准则:**<br />两个核心思想,1. 目标函数有足够的下降 2. 一维搜索的步长λ不应该太小。<br />每一次下降的步长够小才能保证近似值的精准度,就像牛顿法那样分的步骤越多越精准,但是步长太小也会导致你的机器学习一直在在地停留没有进步。数学表达式:<br /><br />Matlab实现```matlabfunction mk=armijo(xk,dk )beta=0.5; sigma=0.2;m=0; mmax=20;while (m<=mmax)if(fun(xk+beta^m*dk)<=fun(xk)+sigma*beta^m*gfun(xk)'*dk)mk=m; break;endm=m+1;endalpha=beta^mknewxk=xk+alpha*dkfk=fun(xk)newfk=fun(newxk)————————————————版权声明:本文为CSDN博主「斑马L*」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/qq_47326711/article/details/118075514
python实现
def armijo_goldstein(f,df,d,x,lambda_max,p,t):'''f=函数df=导数d= 矢量方向x=当前点lambda_max=最大步长p= 公示里面的p用来调整步长的t= 上一步的时间相当于游戏存档'''true_false = 0a= 0b = lambda_maxfx = f(x)df = df(x)last_step = fxnext_step = np.dot(df,d) '用numpy朝着d方向精确求导一个梯度'lambda0 = b*random.unifrom(0,1)while(true_false==0):new_fx = f(x+lambda0 * d)curr_step = new_fxif (curr_step-last_step) <= (p * lambda0 * next_step): '如果近似步长小于最大上界'if (curr_step - last_step) >= ((1-p) * lambda0 * next_step): '近似步长大于最小下界'true_false = 1else:'步长太小,使用binary提高a来寻找更适中的lambda'a = lambda0b = bif (b < lambda_max):lambda0 = (a+b)/2else: '梯度爆炸问题,回到上一步存档'lambda0 = t* lambd0else:'过大了,减少上界重新选步长'a = ab = lambda0lambda0 = (a+b) /2return lambda0'''版权声明:蒙特卡洛树正在找图灵的猫'''
Wolfe-Powell准则(ama505)
Armijo-Goldstein准则可能会把极小值点(可接受的区间)判断在外,因此使用wolfe-powell准则
wolfe-powell准则也有两个数学表达式,第一个和armijo-goldstein一样,第二个是:
这个是一个关于梯度的式子。
算法:
【1】筛选数据
在搜索区间[0,_λ_max] 上选定初始探测点λ0,代入计算好的 f ( 0 ) , f ′ ( 0 ) ,给出可接受系数
【2】检查步长lambda合格否
如果,成功,取下一步,否则缩小上界重新选择下探点
【3】检查下探点是否过小
步骤类似于python实现
[
](https://blog.csdn.net/qq_43940950/article/details/117566544)
拟牛顿法BFGS(ama505)
- 什么是拟牛顿法
牛顿法可以快速收敛,迭代次数少但是每一次都需要计算矩阵的逆导致计算量很大。因此拟牛顿法就是引入了Hessian矩阵的近似矩阵可以避免每次迭代都计算矩阵的逆。它的收敛速度介于梯度下降法和牛顿法之间。
- 原理
在机器学习中经常碰到非线性优化问题,一些算法试图求解一个非线性极小点,最常用的就是BFGS和L-BFGS算法。




- 实现
其实现在python里面有scipy包里面的optimizer内置函数可以直接用,已经有更好的optimizer了,比如SGD/BGD
#coding:UTF-8from numpy import *from function import *def bfgs(fun, gfun, x0):result = []maxk = 500rho = 0.55sigma = 0.4m = shape(x0)[0]Bk = eye(m)k = 0while (k < maxk):gk = mat(gfun(x0))#计算梯度dk = mat(-linalg.solve(Bk, gk))m = 0mk = 0while (m < 20):newf = fun(x0 + rho ** m * dk)oldf = fun(x0)if (newf < oldf + sigma * (rho ** m) * (gk.T * dk)[0,0]):mk = mbreakm = m + 1#BFGS校正x = x0 + rho ** mk * dksk = x - x0yk = gfun(x) - gkif (yk.T * sk > 0):Bk = Bk - (Bk * sk * sk.T * Bk) / (sk.T * Bk * sk) + (yk * yk.T) / (yk.T * sk)k = k + 1x0 = xresult.append(fun(x0))return result'''代码来源:https://blog.csdn.net/xiaopihaierletian/article/details/73950484'''
共轭梯度法(Conjugate Gradient Method)(ama505)
- 介绍
共轭梯度法(Conjugate Gradient)是介于最速下降法与牛顿法之间的一个方法,它仅需利用一阶导数信息,但克服了最速下降法收敛慢的缺点,又避免了牛顿法需要存储和计算Hesse矩阵并求逆的缺点,共轭梯度法不仅是解决大型线性方程组最有用的方法之一,也是解大型非线性最优化最有效的算法之一。 在各种优化算法中,共轭梯度法是非常重要的一种。其优点是所需存储量小,具有步收敛性,稳定性高,而且不需要任何外来参数。
共轭梯度法最初由Hesteness和Stiefel于1952年为求解线性方程组而提出的。后来,人们把这种方法用于求解无约束最优化问题,使之成为一种重要的最优化方法。
共轭梯度法的基本思想是把共轭性与最速下降方法相结合,利用已知点处的梯度构造一组共轭方向,并沿这组方向进行搜素,求出目标函数的极小点。根据共轭方向基本性质,这种方法具有二次终止性。
- 原理与数学推理
https://www.cnblogs.com/walccott/p/4956966.html
https://blog.csdn.net/Liang_Ling/article/details/78552788
- 实现
共轭梯度法。一种求解数学特定线性方程组Ax=b的数值解的迭代方法。
要求矩阵A对称(symmetric)且正定(positive definite)。
def Conjugate_Gradient(e=1e-1, lambda0=0.01,x_init):x = x_initdf = grad(x)'grad求导‘p = -dfcosts = [cost(x)]while abs(df[0]) > e or abs(df[1]) > e:x1 = armijo_goldstein(x,df,p,lamda0) '一维搜索都可以用‘df1 = grad(x1)alpha_t = alpha(df1, df) '计算两次求导梯度差‘p1 = -df1 + alpha_t*pcurrent_cost = cost(x1) '用新的x1算出新的cost‘costs.append(current_cost)'更新参数‘x = x1df = df1p = p1return costs, x'''蒙特卡洛树正在找图灵的猫‘’‘
深度学习入门
环境安装
#环境安装#python#https://www.python.org/downloads/GPU>= 1080tiRAM >= 64gb方法二:使用google colaboratory方法三:使用Jupyter Notebook下载CUDA/Anacondahttps://oreil.ly/9hAxg安装pytorchconda install pytorch torchvision -c pytorchjupyter notebookimport torchprint(torch.cuda.is_available())
#导入numpyimport numpy as npx = np.array([1,2,3])y = np.array([2,4,6])# >>>x + y = ([3,6,9])#matrix muultiplicationx = ([[1,2],[3,4]])y = ([10,20])# >>>x*y = ([[10,40],[30,80]])#转化为一维数组x = x.flatten()import matplotlib.pyplot as plt#draw graphplt.plot(x,y1, label = "sales")plt.plot(x,y2,linestyle='--',label = "cost")plt.xlabel("x")plt.ylabel("y")plt.title("sales & cost")img = imread('../Destop/lena.png')plt.show()#与门def and_door(x1,x2):x = np.array([x1,x2])w = np.array([0.5,0.5])theta = -0.8tmp = np.sum(w*x)+thetaif tmp <= 0 :return 0else:return 1#与非门def NAND(x1,x2):x = np.array([x1,x2])w = np.array([-0.5,-0.5])theta = 0.8tmp = np.sum(w*x)+thetaif tmp <= 0 :return 0else:return 1#或门def or_door(x1,x2):x = np.array([x1,x2])w = np.array([0.5,0.5])theta = -0.3tmp = np.sum(w*x)+thetaif tmp <= 0 :return 0else:return 1#异或门def XOR(x1,x2):s1 = NAND(x1,x2)s2 = or_door(x1,x2)y = and_door(s1,s2)return y
非线性函数activation function
#activation function#非线性函数#sigmoid fun#h(x) = 1/(1+exp(-x))def sigmoid(x):return 1/(1 + np.exp(-x))#step functiondef step_fun(x):y = x >0return y.astype(np.int)
线性函数
#ReLUdef relu(x):return np.maximum(0,x)
多维数组
A= np.array([1,2,3,4])B = np.array([[1,2],[3,4],[5,6]])np.ndim(A) = 1np.ndim(B) = 2A.shape = (4,)B.shape = (3,2)A.shape[0] = 4#shape is tuple#multnp.dot(A,B)
基本三元神经实现
def network():net = {}net['w1'] = np.array([ [x1,x2,x3],[y1,y2,y3] ])net['w2'] = np.array([ [x1,x2],[y1,y2],[z1,z2] ])net['w3'] = np.array([ [x1,x2,x3],[y1,y2,y3] ])net['b1'] = np.array([ [t1,t2,t3] ])net['b2'] = np.array([ [t1,t2] ])net['b3'] = np.array([ [t1,t2] ])return netdef forward(net,x):w1,w2,w3 = net['w1'], net['w2'], net['w3']b1,b2,b3 = net['b1'], net['b2'], net['b3']a1 = np.dot(x,w1) +b1z1 = sigmoid(a1)a2 = np.dot(z1,w2) +b2z2 = sigmoid(a2)a3 = np.dot(z2,w3) + b3res = identity_function(a3) #let output.shape = input.shapereturn resnet = network()x = np.array([1,0.5])y = forward(net,x)
很多事情,尽量更新
softmax函数
softmax是一个总是输出0到1之间的实数的一个函数,其实可以理解把每一个结果变成一个可能发生的概率。因为即使使用了softmax各个元素之间的大小关系也不会发生变化。
def softmax(a):exp_a = np.exp(a)sum_exp_a = np.sum(exp_a)res = exp_a / sum_exp_areturn res#因为计算机的运算存在缺陷会导致指数函数的值变得非常大没办法计算因此直接使用:def softmax(x):if x.ndim == 2:x = x.Tx = x - np.max(x, axis=1) #稳定概率,剪掉最大的元素,axis=0是列,axis=1是行y = np.exp(x) / np.sum(np.exp(x), axis=0)return y.Tx = x - np.max(x) # 溢出对策return np.exp(x) / np.sum(np.exp(x))
MNIST 数据集
mnist数据集就是一堆从0到9的手写数字图像集:
使用这个mnist.py可以将数据集下载并转化成Numpy数组来处理
# coding: utf-8try:import urllib.requestexcept ImportError:raise ImportError('You should use Python3')import os.pathimport gzipimport pickleimport osimport numpy as npurl_base = 'http://yann.lecun.com/exdb/mnist/'key_file = {'train_img':'train-images-idx3-ubyte.gz','train_label':'train-labels-idx1-ubyte.gz','test_img':'t10k-images-idx3-ubyte.gz','test_label':'t10k-labels-idx1-ubyte.gz'}dataset_dir = os.path.dirname(os.path.abspath(__file__))save_file = dataset_dir + "/mnist.pkl"train_num = 60000test_num = 10000img_dim = (1, 28, 28)img_size = 784def _download(file_name):file_path = dataset_dir + "/" + file_nameif os.path.exists(file_path):returnprint("Downloading " + file_name + " ... ")urllib.request.urlretrieve(url_base + file_name, file_path)print("Done")def download_mnist():for v in key_file.values():_download(v)def _load_label(file_name):file_path = dataset_dir + "/" + file_nameprint("Converting " + file_name + " to NumPy Array ...")with gzip.open(file_path, 'rb') as f:labels = np.frombuffer(f.read(), np.uint8, offset=8)print("Done")return labelsdef _load_img(file_name):file_path = dataset_dir + "/" + file_nameprint("Converting " + file_name + " to NumPy Array ...")with gzip.open(file_path, 'rb') as f:data = np.frombuffer(f.read(), np.uint8, offset=16)data = data.reshape(-1, img_size)print("Done")return datadef _convert_numpy():dataset = {}dataset['train_img'] = _load_img(key_file['train_img'])dataset['train_label'] = _load_label(key_file['train_label'])dataset['test_img'] = _load_img(key_file['test_img'])dataset['test_label'] = _load_label(key_file['test_label'])return datasetdef init_mnist():download_mnist()dataset = _convert_numpy()print("Creating pickle file ...")with open(save_file, 'wb') as f:pickle.dump(dataset, f, -1)print("Done!")def _change_one_hot_label(X):T = np.zeros((X.size, 10))for idx, row in enumerate(T):row[X[idx]] = 1return Tdef load_mnist(normalize=True, flatten=True, one_hot_label=False):"""读入MNIST数据集Parameters----------normalize : 将图像的像素值正规化为0.0~1.0one_hot_label :one_hot_label为True的情况下,标签作为one-hot数组返回one-hot数组是指[0,0,1,0,0,0,0,0,0,0]这样的数组flatten : 是否将图像展开为一维数组Returns-------(训练图像, 训练标签), (测试图像, 测试标签)"""if not os.path.exists(save_file):init_mnist()with open(save_file, 'rb') as f:dataset = pickle.load(f)if normalize:for key in ('train_img', 'test_img'):dataset[key] = dataset[key].astype(np.float32)dataset[key] /= 255.0if one_hot_label:dataset['train_label'] = _change_one_hot_label(dataset['train_label'])dataset['test_label'] = _change_one_hot_label(dataset['test_label'])if not flatten:for key in ('train_img', 'test_img'):dataset[key] = dataset[key].reshape(-1, 1, 28, 28)return (dataset['train_img'], dataset['train_label']), (dataset['test_img'], dataset['test_label'])if __name__ == '__main__':init_mnist()
#接着可以使用load_mnist()读入mnist数据#normalize设置是否将图像正规化为0~1的实数,否则像素保持0~255#flatten设置是否展开图像为一维,否则保持1*28*28#one-hot表示仅仅正确的解的标签为1其余标签为0# coding: utf-8import sys, ossys.path.append(os.pardir) # 为了导入父目录的文件而进行的设定import numpy as npfrom dataset.mnist import load_mnistfrom PIL import Imagedef img_show(img):pil_img = Image.fromarray(np.uint8(img))pil_img.show()(x_train, t_train), (x_test, t_test) = load_mnist(flatten=True, normalize=False)img = x_train[0]label = t_train[0]print(x_train.shape) #60000,784print(t_train.shape) #60000print(x_test.shape) #10000,784print(t_test.shape) #10000print(label) # 5print(img.shape) # (784,)img = img.reshape(28, 28) # 把图像的形状变为原来的尺寸print(img.shape) # (28, 28)img_show(img)
#接着使用之前的sigmoid,softmax和forward来进行基本的机器学习# coding: utf-8import sys, ossys.path.append(os.pardir) # 为了导入父目录的文件而进行的设定import numpy as npimport picklefrom dataset.mnist import load_mnistdef softmax(x):if x.ndim == 2:x = x.Tx = x - np.max(x, axis=0)y = np.exp(x) / np.sum(np.exp(x), axis=1)return y.Tx = x - np.max(x) # 溢出对策return np.exp(x) / np.sum(np.exp(x))def sigmoid(x):return 1 / (1 + np.exp(-x))def get_data():(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, flatten=True, one_hot_label=False)return x_test, t_testdef init_network():with open("sample_weight.pkl", 'rb') as f:network = pickle.load(f)return networkdef predict(network, x):W1, W2, W3 = network['W1'], network['W2'], network['W3']b1, b2, b3 = network['b1'], network['b2'], network['b3']a1 = np.dot(x, W1) + b1z1 = sigmoid(a1)a2 = np.dot(z1, W2) + b2z2 = sigmoid(a2)a3 = np.dot(z2, W3) + b3y = softmax(a3)return yx, t = get_data()network = init_network()accuracy_cnt = 0for i in range(len(x)):y = predict(network, x[i])p= np.argmax(y) # 获取概率最高的元素的索引if p == t[i]:accuracy_cnt += 1print("Accuracy:" + str(float(accuracy_cnt) / len(x)))##Accuracy:0.9352
批处理batch
例如输入数据是100x784,然后输出数据是100x10.这种打包数据是batch,批处理可以缩短每张图像处理的时间
#批处理的实现·x, t = get_data()network = init_network()batch_size = 100acc = 0for i in range(0,len(x),batch_size):x_batch = x[i:i+batch_size]y_batch = predict(network,x_batch)p = np.argmax(y_batch,axis = 1)#p == t[i:i+batch_size] 是布尔值,将np.sum会将所有的TRUE加起来acc += np.sum(p == t[i:i+batch_size])print("Accuracy:" + str(float(acc)/len(x)))
#argmaxa = array([[10, 11, 12],[13, 14, 15]])np.argmax(a)>>5np.argmax(a, axis=0)#axis=0 从列出发>>array([1, 1, 1])np.argmax(a, axis=1)#从行出发>>array([2, 2])
训练与测试数据
在计算机视觉领域中,常用的特征量为SIFT,SURF,HOG,然后使用这个特征量将图像数据转化为向量。
对转化后的向量使用机器学习的SVM,KNN等分类器进行学习。
在机器学习中,一般将数据分为训练数据和测试数据。有训练数据的机器学习也称为监督学习,反之为无监督学习。某个数据过度拟合就是过拟合over fitting
