Python实现线性回归2,梯度下降算法

接上篇

4.梯度下降算法

《斯坦福大学公开课 :机器学习课程》吴恩达讲解第二课时,是直接从梯度下降开始讲解,最后采用向量和矩阵的方式推导了解析解,国内很多培训视频是先讲解析解后讲梯度下降,个人认为梯度下降算法更为重要,它是很多算法(逻辑回归、神经网络)都可以共用的,线性回归仅仅是凑巧有全局最小值的解法,有解析解,其他大部分算法都需要遍历数据寻找全局(其实本质上是局部最优)最优解的过程。
解析解直接向量运算存在的问题:(1)矩阵必须是满秩的,如果不是,python也能模糊处理。(2)运算性能,矩阵扩大化后,量级增大对性能影响明显。
梯度下降不仅限于线性回归,非线性和神经网络同样适用。

在线性回归中,θ通过α学习速率在每个J( θ) 减小的维度上进行一个 不定式 θ参数的递减,不断更新 θ{i} 的值直到 J(θ) 收敛,达到最小值。类比于下山,每次尝试找比这个位置低的位置,一步一步到达山底(即我们求的最小值,详细请看参考资料8)

4.1批量梯度下降算法

老师常常教导我们梯度下降算法这么经典的算法,一定要自己动手推导公式,自己用程序来实现以下,我一直嗤之以鼻,线性回归这么简单的算法还需要自己敲代码实现一下吗?最近工作闲暇时,我自己用Python实现了下该算法,不敲不知道,一敲吓一大跳,太多坑在里面了,整整坑在里面2天时间,检查多遍代码最后发现是数据问题,学习率α需要取非常非常小的值才能收敛,否则程序一直处于震荡状态无法找到近似最小值。说了那么多废话,下面直接贴代码,代码里备注说明很完善,很明了,很清晰了,大家应该能看懂吧o( ̄︶ ̄)o
在这里插入图片描述
在这里插入图片描述

def linearRegBgd2(x,y,alpha=0.005,lamba=0.005,loop_max=1000):#alpha = 0.0000001      #学习率步长,learning rate#lamba=0.005     #惩罚系数 '''参考链接:https://blog.csdn.net/mango_badnot/article/details/52328740 已将原作者计算过程进行了大量修改,就相当于是我原创了吧,将原计算的三重for循环重写为一重for循环,将运算修改为了矩阵运算原作者构造的X特征是按行存储的,与常见数据不太一致,X中第一行为特征1,第二行为特征2此函数将使用正常数据,X特征按列存储,每行是一条记录批量梯度下降算法公式:theta=theta + alpha * sum( (y-y_hat) * x)'''np.set_printoptions(precision=4) # 设置numpy输出4位小数n=len(x[0]) # 取第一行数据,查看数据列数theta=np.zeros(n)      # 初始化theta数组,默认全为0for times in range(loop_max):y_hat=np.dot(x,theta.T).reshape((-1,1))loss= (y_hat-y)  #此处是y_hat-y,对应的theta求解处增加了一个负号loss_n=np.array([]) # 为方便直接用矩阵实现sum( (y-y_hat) * x),产生多列loss乘以loss后求和if n==1: # 判断x矩阵有几列,列为1的时候单独处理loss_n=losselse:for i in range(1,n):# 判断x矩阵有几列,列为大于2的时候,产生n列loss#print(i)if i==1:loss_n = np.column_stack((loss, loss))elif i>1:loss_n = np.column_stack((loss_n, loss))theta_old=theta # 记录迭代前的theta#tmp=alpha*(loss_n*x).sum(axis=0)theta=theta - (alpha*(x*loss_n)).sum(axis=0) #+lamba*theta   #使用矩阵求解theta,注意此处的负号,loss*x后按特征列求和作为theta,注意上方本来想实现惩罚项的,但没有想明白怎么实现if (theta-theta_old).all()<0.001: # 判断前后两次theta变换情况,当变化率很小时跳出循环break#print('x:',x,'y:',y,'loss:',loss)#print('y_hat:',y_hat.T)#print('times:',times,'theta:',theta)#print('')return theta

4.2随机梯度下降算法

随机梯度下降就是每一个样本更新一次权值,超过样本范围就循环从第一个样本再循环,同等数据量情况下(数据量不是特别巨大时)训练速度与批量梯度下降要慢一些,但是适合在线学习,来一条数据迭代训练一次。
在这里插入图片描述

def linearRegSgd(x,y,alpha=0.005,lamba=0.005,loop_max=10000):#alpha = 0.0000001      #学习率步长,learning rate#lamba=0.005     #惩罚系数 '''随机梯度下降算法公式:theta=theta + alpha * (y-y_hat) * xalpha=0.01lamba=0.005'''np.set_printoptions(precision=4) # 设置numpy输出4位小数n=len(x[0]) # 取第一行数据,查看数据列数theta=np.zeros(n)      # 初始化theta数组,默认全为0for times in range(loop_max):for i  in range(0,len(x)): # 取其中一条数据进行梯度下降# i=0y_hat=np.dot(x[i],theta.T).reshape((-1,1))loss= (y_hat-y[i])  #此处是y_hat-y,对应的theta求解处增加了一个负号theta_old=theta # 记录迭代前的thetatheta=theta - alpha*x[i]*loss[0] #+lamba*theta#求解theta,注意此处的负号,注意上方本来想实现惩罚项的,但没有想明白怎么实现if (theta-theta_old).all()<0.001: # 判断前后两次theta变换情况,当变化率很小时跳出循环break
#            print('x:',x,'y:',y,'loss:',loss)
#            print('y_hat:',y_hat.T)
#            print('times:',times,'theta:',theta)
#            print('')return theta

4.3 mini-batch梯度下降算法

如果不是每拿到一个样本即更改梯度,而是用若干个样本的平均梯度作为更新方向,这就是Mini-batch梯度下降算法。

def linearRegMgd(x,y,alpha=0.005,lamba=0.005,loop_max=1000,batch_size=9):#alpha = 0.0000001      #学习率步长,learning rate#lamba=0.005     #惩罚系数 '''mini-batch梯度下降算法公式:每次使用batch_size个数据进行计算for i=1 to m: theta=theta + alpha * (y-y_hat) * x'''np.set_printoptions(precision=4) # 设置numpy输出4位小数n=len(x[0]) # 取第一行数据,查看数据列数theta=np.zeros(n)      # 初始化theta数组,默认全为0for times in range(loop_max):for i in range(0,int(len(x)/batch_size)+1):#print('i:',i,x[i*batch_size:(i+1)*batch_size])x_mini=x[i*batch_size:(i+1)*batch_size]y_mini=y[i*batch_size:(i+1)*batch_size]y_hat=np.dot(x_mini,theta.T).reshape((-1,1))loss= (y_hat-y_mini)  #此处是y_hat-y,对应的theta求解处增加了一个负号loss_n=np.array([]) # 为方便直接用矩阵实现sum( (y-y_hat) * x),产生多列loss乘以loss后求和if n==1: # 判断x矩阵有几列,列为1的时候单独处理loss_n=losselse:for i in range(1,n):# 判断x矩阵有几列,列为大于2的时候,产生n列loss#print(i)if i==1:loss_n = np.column_stack((loss, loss))elif i>1:loss_n = np.column_stack((loss_n, loss))theta_old=theta # 记录迭代前的theta#tmp=alpha*(loss_n*x).sum(axis=0)theta=theta - (alpha*(x_mini*loss_n)).sum(axis=0) #+lamba*theta   #使用矩阵求解theta,注意此处的负号,loss*x后按特征列求和作为theta,注意上方本来想实现惩罚项的,但没有想明白怎么实现if (theta-theta_old).all()<0.001: # 判断前后两次theta变换情况,当变化率很小时跳出循环break#print('x:',x,'y:',y,'loss:',loss)#print('y_hat:',y_hat.T)#print('times:',times,'theta:',theta)#print('')return theta

以上梯度下降算法完整代码如下

# -*- coding: utf-8 -*-
"""@Time    : 2018/10/22 17:23@Author  : hanzi5@Email   : **@163.com@File    : linear_regression_bgd.py@Software: PyCharm
"""
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegressiondef load_dataset(n): # 原作者产生数据的函数noise = np.random.rand(n)X = [[x, 1.] for x in range(n)]y = [(0.5 * X[i][0]  + 1. + noise[i]) for i in range(n)]return np.array(X).T, np.array(y).T # 注意X,W,y的维数def linearRegLsq(x,y):# 最小二乘法直接求解thetaxtx = np.dot(x.T, x)if np.linalg.det(xtx) == 0.0: # 判断xtx行列式是否等于0,奇异矩阵不能求逆print('Can not resolve the problem')returntheta_lsq = np.dot(np.dot(np.linalg.inv(np.dot(x.T, x)), x.T), y)return theta_lsqdef linearRegBgd1(x,y,alpha=0.005,lamba=0.005,loop_max=1000):#alpha = 0.0000001      #学习率步长,learning rate#lamba=0.005     #惩罚系数 '''已将原作者计算过程进行了大量修改,已将原作者计算过程进行了大量修改,就相当于是我原创了吧,将原计算的三重for循环重写为一重for循环参考链接:https://blog.csdn.net/mango_badnot/article/details/52328740 原作者构造的X特征是按行存储的,与常见数据不太一致,X中第一行为特征1,第二行为特征2批量梯度下降算法公式:theta=theta + alpha * sum( (y-y_hat) * x)2018-10-22 17:18 测试通过,此函数不做多的备注了,详细备注放在了linearRegBgd2里'''np.set_printoptions(precision=4) # 设置numpy输出4位小数n=len(x) # 取第一行数据,查看数据列数theta=np.zeros(n)      # 初始化theta数组,默认全为0for times in range(loop_max):y_hat=np.dot(x.T,theta)loss= y-y_hatfor i in range(1,n):if i==1:loss_n = np.row_stack((loss, loss))elif i>1:loss_n = np.row_stack((loss_n, loss))theta_old=thetatheta=theta+(alpha*x.T*loss_n.T).sum(axis=0) #+lamba*thetaif (theta-theta_old).all()<0.001:break#print('x:',x,'y:',y,'loss:',loss)#print('times:',times,'theta:',theta)#print('')return thetadef linearRegBgd2(x,y,alpha=0.005,lamba=0.005,loop_max=1000):#alpha = 0.0000001      #学习率步长,learning rate#lamba=0.005     #惩罚系数 '''参考链接:https://blog.csdn.net/mango_badnot/article/details/52328740 已将原作者计算过程进行了大量修改,就相当于是我原创了吧,将原计算的三重for循环重写为一重for循环,将运算修改为了矩阵运算原作者构造的X特征是按行存储的,与常见数据不太一致,X中第一行为特征1,第二行为特征2此函数将使用正常数据,X特征按列存储,每行是一条记录批量梯度下降算法公式:theta=theta + alpha * sum( (y-y_hat) * x)'''np.set_printoptions(precision=4) # 设置numpy输出4位小数n=len(x[0]) # 取第一行数据,查看数据列数theta=np.zeros(n)      # 初始化theta数组,默认全为0for times in range(loop_max):y_hat=np.dot(x,theta.T).reshape((-1,1))loss= (y_hat-y)  #此处是y_hat-y,对应的theta求解处增加了一个负号loss_n=np.array([]) # 为方便直接用矩阵实现sum( (y-y_hat) * x),产生多列loss乘以loss后求和if n==1: # 判断x矩阵有几列,列为1的时候单独处理loss_n=losselse:for i in range(1,n):# 判断x矩阵有几列,列为大于2的时候,产生n列loss#print(i)if i==1:loss_n = np.column_stack((loss, loss))elif i>1:loss_n = np.column_stack((loss_n, loss))theta_old=theta # 记录迭代前的theta#tmp=alpha*(loss_n*x).sum(axis=0)theta=theta - (alpha*(x*loss_n)).sum(axis=0) #+lamba*theta   #使用矩阵求解theta,注意此处的负号,loss*x后按特征列求和作为theta,注意上方本来想实现惩罚项的,但没有想明白怎么实现if (theta-theta_old).all()<0.001: # 判断前后两次theta变换情况,当变化率很小时跳出循环break#print('x:',x,'y:',y,'loss:',loss)#print('y_hat:',y_hat.T)#print('times:',times,'theta:',theta)#print('')return thetadef linearRegSgd(x,y,alpha=0.005,lamba=0.005,loop_max=10000):#alpha = 0.0000001      #学习率步长,learning rate#lamba=0.005     #惩罚系数 '''随机梯度下降算法公式:for i=1 to m: theta=theta + alpha * (y-y_hat) * xalpha=0.01lamba=0.005'''np.set_printoptions(precision=4) # 设置numpy输出4位小数n=len(x[0]) # 取第一行数据,查看数据列数theta=np.zeros(n)      # 初始化theta数组,默认全为0for times in range(loop_max):for i  in range(0,len(x)): # 取其中一条数据进行梯度下降# i=0y_hat=np.dot(x[i],theta.T).reshape((-1,1))loss= (y_hat-y[i])  #此处是y_hat-y,对应的theta求解处增加了一个负号theta_old=theta # 记录迭代前的thetatheta=theta - alpha*x[i]*loss[0] #+lamba*theta#求解theta,注意此处的负号,注意上方本来想实现惩罚项的,但没有想明白怎么实现if (theta-theta_old).all()<0.001: # 判断前后两次theta变换情况,当变化率很小时跳出循环break
#            print('x:',x,'y:',y,'loss:',loss)
#            print('y_hat:',y_hat.T)
#            print('times:',times,'theta:',theta)
#            print('')return thetadef linearRegMgd(x,y,alpha=0.005,lamba=0.005,loop_max=1000,batch_size=9):#alpha = 0.0000001      #学习率步长,learning rate#lamba=0.005     #惩罚系数 '''mini-batch梯度下降算法公式:每次使用batch_size个数据进行计算for i=1 to m: theta=theta + alpha * (y-y_hat) * x'''np.set_printoptions(precision=4) # 设置numpy输出4位小数n=len(x[0]) # 取第一行数据,查看数据列数theta=np.zeros(n)      # 初始化theta数组,默认全为0for times in range(loop_max):for i in range(0,int(len(x)/batch_size)+1):#print('i:',i,x[i*batch_size:(i+1)*batch_size])x_mini=x[i*batch_size:(i+1)*batch_size]y_mini=y[i*batch_size:(i+1)*batch_size]y_hat=np.dot(x_mini,theta.T).reshape((-1,1))loss= (y_hat-y_mini)  #此处是y_hat-y,对应的theta求解处增加了一个负号loss_n=np.array([]) # 为方便直接用矩阵实现sum( (y-y_hat) * x),产生多列loss乘以loss后求和if n==1: # 判断x矩阵有几列,列为1的时候单独处理loss_n=losselse:for i in range(1,n):# 判断x矩阵有几列,列为大于2的时候,产生n列loss#print(i)if i==1:loss_n = np.column_stack((loss, loss))elif i>1:loss_n = np.column_stack((loss_n, loss))theta_old=theta # 记录迭代前的theta#tmp=alpha*(loss_n*x).sum(axis=0)theta=theta - (alpha*(x_mini*loss_n)).sum(axis=0) #+lamba*theta   #使用矩阵求解theta,注意此处的负号,loss*x后按特征列求和作为theta,注意上方本来想实现惩罚项的,但没有想明白怎么实现if (theta-theta_old).all()<0.001: # 判断前后两次theta变换情况,当变化率很小时跳出循环break#print('x:',x,'y:',y,'loss:',loss)#print('y_hat:',y_hat.T)#print('times:',times,'theta:',theta)#print('')return thetaif __name__ == "__main__":path = 'D:/python_data/8.Advertising.csv'data = pd.read_csv(path)  # TV、Radio、Newspaper、Sales#data_matrix = data.as_matrix(columns=['TV', 'Radio', 'Newspaper', 'Sales'])  # 转换数据类型data_array = data.values[:,1:]  # 转换数据类型,去除第一列序号列x = data_array[:, :-1] #去除y对应列的数据,其他列作为xy = data_array[:, -1].reshape((-1,1))# 0、绘制图像,查看数据分布情况plt.plot(data['TV'], y, 'ro', label='TV')plt.plot(data['Radio'], y, 'g^', label='Radio')plt.plot(data['Newspaper'], y, 'mv', label='Newspaer')plt.legend(loc='lower right')plt.grid()plt.show()# 1、使用sklearn LinearRegression包求解θlinreg = LinearRegression()model = linreg.fit(x, y)print('')print('1、sklearn LinearRegression包求解θ:','coef:', linreg.coef_[0],',intercept:', linreg.intercept_)# 2、最小二乘法,直接求解析解θtheta_lsq = linearRegLsq(x,y)print('')print('2、最小二乘法,theta解析解:',theta_lsq.reshape(1,3)[0])# 3、批量梯度下降求解theta# 注意下面两个函数alpha都是非常小的值,取过大的值时,不收敛#x1, y1 = load_dataset(10)#theta1=linearRegBgd1(x1, y1)theta1=linearRegBgd1(x.T, y.T,alpha = 0.0000001)print('')print('3.1、批量梯度下降,linearRegBgd1函数,theta:',theta1)theta2=linearRegBgd2(x, y,alpha = 0.0000001)print('')print('3.2、批量梯度下降,linearRegBgd2函数,theta:',theta2)theta3=linearRegSgd(x, y,alpha = 0.000001,loop_max=10000)print('')print('3.3、随机梯度下降,linearRegSgd函数,theta:',theta3)theta4=linearRegMgd(x, y,alpha = 0.000001,loop_max=10000,batch_size=11)print('')print('3.4、mini-batch梯度下降,linearRegMgd函数,theta:',theta4)

程序运行计算结果:
在这里插入图片描述

数据见以下链接,复制到txt文档中,另存为CSV格式即可。
数据

参考资料:
1、python实现线性回归
2、机器学习:线性回归与Python代码实现
3、python实现简单线性回归
4、Machine-Learning-With-Python
5、《机器学习》西瓜书,周志华
6、机器学习视频,邹博
7、 斯坦福大学公开课 :机器学习课程
8、马同学高等数学 如何直观形象的理解方向导数与梯度以及它们之间的关系?
9、【机器学习】线性回归的梯度下降法

转载于:https://www.cnblogs.com/hanzi5/p/10105622.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/249161.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mac 下用 brew 安装mongodb

mac 下安装mongoDB一般俩种方法. (1)下载源码,解压,编译,配置,启动 比较艰难的一种模式. (2)brew install mongodb ,然后就可以悠闲的品一口茶,顺便瞄一眼网易新闻,这是一种傻瓜模式. 但傻瓜模式也有人为干预的时候,粗略说一下使用brew 安装mongodb 1 zhangzhimoke:~/code$…

比较python类的两个instance(对象) 是否相等

http://www.yihaomen.com/article/python/281.htm 比较python类的两个instance(对象) 是否相等 作者:轻舞肥羊 日期:2012-10-25 字体大小: 小 中 大对于同一个Class,可以创建不同的实例(instance), 如何比较这两个 instance 是否相等呢&#xff1f;我们知道&#xff0c;对于计算…

Mybaits插入记录返回主键值

某些情况进行insert时不知道主键值&#xff08;主键为自增&#xff09;&#xff0c;例如系统新增用户时&#xff0c;有用户序号&#xff08;主键 自增&#xff09;&#xff0c;用户名&#xff0c;密码。插入时只需插入用户名和密码&#xff0c;之后取得mysql自增的序号。 如下为…

CAS单点登录原理简单介绍

1. SSO简介 1.1 单点登录定义 单点登录(Single sign on)&#xff0c;英文名称缩写SSO&#xff0c;SSO的意思就是在多系统的环境中&#xff0c;登录单方系统&#xff0c;就可以在不用再次登录的情况下访问相关受信任的系统。也就是说只要登录一次单体系统就可以。计划在项目中加…

前端跨域通信的几种方式

前言 前端通信类的问题&#xff0c;主要包括以下内容&#xff1a; 1、什么是同源策略及限制 同源策略是一个概念&#xff0c;就一句话。有什么限制&#xff0c;就三句话。能说出来即可。 2、前后端如何通信 如果你不准备&#xff0c;估计也就只能说出ajax。 3、如何创建Aja…

Luogu 3698 [CQOI2017]小Q的棋盘

BZOJ 4813 虽然数据范围很迷人&#xff0c;但是想树形$dp$没有前途。 先发现一个事情&#xff0c;就是我们可以先选择一条链&#xff0c;最后要走到这一条链上不回来&#xff0c;走到链上的点每一个只需要一步&#xff0c;而如果要走这条链之外的点&#xff0c;一个点需要走两步…

解决vue打包后静态资源路径错误的问题

vue项目完成的最后一步就是打包部署上线&#xff0c;但是打包部署的过程往往不是那么一帆风顺的&#xff0c;现将遇到问题和解决方案记录如下。 图片路径问题 起因&#xff1a; 页面中引入资源的方式往往有如下几种 * HTML标签中直接引入图片&#xff0c; 如 <img src&qu…

DOMBOM(source、methods、contents、Application)

何为DOM&#xff1f; Document Object Model Dom&#xff0c;是W3C组织推荐的处理可扩展标志语言的标准编程接口。在网页上&#xff0c;组织页面的对象被组织在一个树形结构中&#xff0c;用来表示文档中对象的标准模型就称为DOM。 可以认为DOM是页面上数据和结构的一个树形表示…

spring-注解---IOC(3)

spring--注解---IOC(3) package com.zwj.bean;public class Blue {public Blue(){System.out.println("blue...constructor");}public void init(){System.out.println("blue...init...");}public void detory(){System.out.println("blue...detory..…

在div中设置文字与内部div垂直居中

要实现如图一所示的结果&#xff1a; html代码如下&#xff1a; <!DOCTYPE html> <html><head lang"zh"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta charset"utf-8" /><title>商…

王之泰201771010131《面向对象程序设计(java)》第九周学习总结

第一部分&#xff1a;理论知识学习部分 第7章异常、日志、断言和调试 概念&#xff1a;异常、异常类型、异常声明、异常抛出、 异常捕获1.异常处理技术2.断言的概念及使用3.基本的调试技巧 1&#xff09;异常的概念 a.Java的异常处理机制可以控制程序从错误产生的 位置转移到能…

Java学习——使用Static修饰符

程序功能&#xff1a;通过两个类 StaticDemo、LX4_1 说明静态变量/方法与实例变量/方法的区别。 package Pack1;public class Try {public static void main(String[] args) {// TODO Auto-generated method stubSystem.out.println("静态变量x"StaticDemo.getX());非…

JavaScript从入门到精通之入门篇(一)概念与语法

入门篇大纲 第一部分 概念与语法 1.JavaScript的历史 2.基本概念 3.JavaScript的使用、调试和异常处理 4.基本词法和变量 5.数据类型和类型转换 6.运算符 算数运算符 赋值运算符 一元运算符 使用一元运算符&#xff0c;将会把所有的内容转换为数值运算&#xff0c;不…

【小记】-005--纯CSS实现的小玩意儿

效果图奉上 代码奉上 <!DOCTYPE html> <html lang"zh"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv"X-UA-Compatible&q…

JavaScript从入门到精通之入门篇(二)函数和数组

入门篇大纲 第二部分 函数与数组 1.函数 函数的定义 普通函数 function 函数名 &#xff08;表达式1…&#xff09; { 代码块 }js是解释性语言&#xff0c;在当前script标签代码执行的开始阶段&#xff0c;就会将普通函数放入堆中&#xff0c;也只是将引用放入堆中&#xf…

一道Python面试题

无意间&#xff0c;看到这么一道Python面试题&#xff1a;以下代码将输出什么&#xff1f; def testFun(): temp [lambda x : i*x for i in range(4)] return temp for everyLambda in testFun(): print (everyLambda(2))脑中默默一想&#xff0c;这还用说么&#xff0c;肯定是…

Windows下的ssh姐妹花 Xshell 和 Xftp

Windows下的ssh姐妹花 Xshell 和 Xftp 今天是3月8号&#xff0c;中国传统的三八妇女节&#xff0c;是距离中国新兴节日三七女生&#xff08;神&#xff09;节最近的一个全国性节日&#xff0c;今天我也是宅在家&#xff0c;研究了一下近日工作上遇到的一个纯软件技术问题。废话…

关于数字证书理解的简单整理以及12306站点证书简单分析

版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 https://blog.csdn.net/sundacheng1989/article/details/25540601 首先简单理解一下什么是数字证书。这里是一篇英文文档&#xff0c;描写叙述的非常形象。形象的描写叙述了什么是公钥。什么是私钥。…

Mac中安装Node和版本控制工具nvm遇到的坑

首先说说常规的安装 1. 下载nvm,使用nvm来管理Node版本 官方文档 windows 版本  https://github.com/coreybutler/nvm-windows mac 版本    https://github.com/creationix/nvm#install-script 命令行 尽量不要用brew&#xff0c;免得掉坑 curl -o- https://raw.githubu…

wepy - 与原生有什么不同(x.wpy)使用实例

源码 1 <template>2 <view classmark wx:if"{{showMark}}">3 <view animation"{{animationData}}" class"animCat">4 <image src"http://osk1hpe2y.bkt.clouddn.com/18-5-30/34559443.jpg"></…