tonglin0325的个人主页

Spring MVC学习笔记——登录和异常处理

1.在WEN-INF文件夹下面,添加一个login.jsp文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>用户登录</title>
</head>
<body>
<form action="user/login" method="post">
用户名:<input type="text" name="username"/><br/>
用户密码:<input type="password" name="password"/><br/>
<input type="submit" value="用户登录"/>
</form>
</body>
</html>

 

2.在UserController.java中加入login

1
2
3
4
5
6
7
8
9
10
11
12
13
@RequestMapping(value="/login",method=RequestMethod.POST)
public String login(String username,String password,HttpSession session){
if(!users.containsKey(username)){
throw new UserException("用户名不存在");
}
User u = users.get(username);
if(!u.getPassword().equals(password)){
throw new UserException("用户密码不正确");
}
session.setAttribute("loginUser", u);
return "redirect:/user/users";
}

 

3.其中需要new UserException,再创建UserException.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package org.common.model;

public class UserException extends RuntimeException {

/**
*
*/
private static final long serialVersionUID = 1L;

public UserException() {
super();
// TODO Auto-generated constructor stub
}

public UserException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}

public UserException(String message) {
super(message);
// TODO Auto-generated constructor stub
}

public UserException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}


}

 如果只是做到这些的话,当输出的用户名和密码错误的时候,报错如下图

 

4.在UserController.java中加入局部异常处理,并在jsp文件夹下面添加error.jsp

 

1
2
3
4
5
6
7
//局部的异常处理,仅仅只能处理这个控制器中的异常
@ExceptionHandler(value={UserException.class})
public String handlerException(UserException e,HttpServletRequest req) {
req.setAttribute("exception",e);
return "error";
}

全文 >>

Hive任务如何计算生成的map和reduce任务

在使用hive时候,需要关注hive任务所消耗的资源,否则可能会出现hive任务过于低效,或者把所查询的数据源拉胯的情况

1.查看当前hive所使用的引擎和配置

使用set语句可以查看当前hive的配置

1
2
set;

查看hive当前使用的engine

1
2
set hive.execution.engine;

 

查看hive.input.format和mapreduce.input.fileinputformat.split.maxsize

1
2
3
hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat
mapreduce.input.fileinputformat.split.maxsize=256000000

全文 >>

Linux学习笔记——Shell部分

1.shell命令

shell是连接linux内核和linux命令的模块

  命令名称  /bin/sh  /bin/csh  /bin/ksh

  chsh -s  输入新的shell,即修改shell

可以使用env命令查看当前的环境变量,可以查看当前使用的是什么shell命令

1
2
env | grep SHELL
SHELL=/bin/zsh

2.使用vi编辑器

键盘输入 功能
i 进入插入模式
esc 进入命令模式
w 将目前文件内容加以保存
q 退出,如果文件有修改会出现错误信息
q! 强制离开vi,并且不保存文件
wq 将修改过的内容保存,并离开vi
set nu 给文件中每一行添加行号
set nonu 取消行号
输入数字 直接输入数字再按esc,可将光标移至该行行首
/字符串 从头查找特定字符串
?字符串 从尾查找特定字符串

3.管道命令:pipe |

1.把一个命令的输出作为另一个命令的输入

1
2
ls -al /etc | less

4.选取命令:cut和grep

cut命令可以将一段消息的某段切出来。

-d接分隔符,-f是取出第几段的意思,-c是以字符串为单位取出固定的字符串范围

1
2
3
ls -F | grep '/' -v | cut -d'.' -f 1  #在取出不是文件夹的文件后,通过分隔符&lsquo;.&rsquo;来分割,取出不包括文件后缀的文件名
ls -F | grep '/' -v | cut -c 1-  #取出第一个字符(包括第一个)之后范围的字符,也可以指定范围1-5

  

grep命令分析一行消息,如果其中有所需要的信息,就将该行取出。

1
2
3
4
5
ls -F | grep '/'  #取出文件夹的名字
ls -F | grep '/' -v  #反向,取出不是文件夹的文件
ls -l | grep ^d #只显示文件夹
ls -l | grep ^- #只显示文件

全文 >>

Ubuntu16.04安装Ranger2.1.0

1.编译ranger项目

1
2
3
4
5
git clone https://github.com/apache/ranger.git
cd ranger
git checkout -b release-ranger-2.1.0 release-ranger-2.1.0
mvn clean package -DskipTests -Drat.skip=true

需要注意的是,ranger2.1.0编译的时候,maven的版本需要大于3.6.0,否则会出现下面报错

1
2
3
4
5
6
7
8
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-enforcer-plugin:1.4.1:enforce (enforce-versions) on project ranger: Some Enforcer rules have failed. Look above for specific messages explaining why the rule failed. -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

编译成功

编译后可以看出target目录下的文件如下

 

2.安装ranger

创建linux ranger用户和组

1
2
3
4
5
6
7
sudo groupadd ranger
sudo useradd ranger -g ranger -r --no-log-init -d /var/lib/ranger
sudo mkdir /var/lib/ranger
sudo mkdir /var/run/ranger
sudo chown -R ranger:ranger /var/lib/ranger
sudo chown -R ranger:ranger /var/run/ranger

全文 >>

机器学习——利用K-均值聚类算法对未标注数据分组

聚类是一种无监督的学习,它将相似的对象归到同一簇中。它有点像全自动分类。聚类方法几乎可以应用到所有对象,簇内的对象越相似,聚类的效果越好。

K-均值(K-means)聚类算法,之所以称之为K-均值是因为它可以发现k个不同的簇,且每个簇的中心采用簇中所含值的均值计算而成。

簇识别(cluster identification)给出簇类结果的含义。假定有一些数据,现在将相似数据归到一起,簇识别会告诉我们这些簇到底都是些什么。

 

K-均值聚类算法

优点:容易实现

缺点:可能收敛到局部最小值,在大规模数据集上收敛较慢

使用数据类型:数值型数据

 

K-均值是发现给定数据集的k个簇的算法。簇个数k是用户给定的,每一个簇通过其质心(centroid),即簇中所有点的中心来描述。

K-均值算法的工作流程是:

1.随机确定k个初始点作为质心

2.然后将数据集中的每个点分配到一个簇中,具体来讲,为每个点找到其最近的质心,并将其分配给该质心所对应的簇。

3.完成之后,每个簇的质心更新为该簇所有点的平均值。

 

全文 >>

机器学习——模型树

和回归树(在每个叶节点上使用各自的均值做预测)不同,模型树算法需要在每个叶节点上都构建出一个线性模型,这就是把叶节点设定为分段线性函数,这个所谓的分段线性(piecewise linear)是指模型由多个线性片段组成。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#####################模型树#####################
def linearSolve(dataSet): #模型树的叶节点生成函数
m,n = shape(dataSet)
X = mat(ones((m,n))); Y = mat(ones((m,1))) #建立两个全部元素为1的(m,n)矩阵和(m,1)矩阵
X[:,1:n] = dataSet[:,0:n-1]; Y = dataSet[:,-1] #X存放所有的特征,Y存放
xTx = X.T*X
if linalg.det(xTx) == 0.0:
raise NameError('This matrix is singular, cannot do inverse,\n\
try increasing the second value of ops')
ws = xTx.I * (X.T * Y) #求线性回归的回归系数
return ws,X,Y

def modelLeaf(dataSet): #建立模型树叶节点函数
ws,X,Y = linearSolve(dataSet)
return ws

def modelErr(dataSet): #模型树平方误差计算函数
ws,X,Y = linearSolve(dataSet)
yHat = X * ws
return sum(power(Y - yHat,2))

main.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# coding:utf-8
# !/usr/bin/env python

import regTrees
import matplotlib.pyplot as plt
from numpy import *

if __name__ == '__main__':
myDat = regTrees.loadDataSet('exp2.txt')
myMat = mat(myDat)
myTree = regTrees.createTree(myMat,regTrees.modelLeaf,regTrees.modelErr,(1,10))
print myTree
regTrees.plotBestFit('exp2.txt')

 

得到两段函数,以0.28为分界

分别为y=3.46877+1.1852x和y=0.001698+11.96477x

而生成该数据的真实模型是y=3.5+1.0x和y=0+12x再加上高斯噪声生成

全文 >>

机器学习——回归树

**  线性回归创建模型需要拟合所有的样本点(局部加权线性回归除外)。当数据拥有众多特征并且特征之间关系十分复杂的时候,构建全局模型的想法就显得太难了,也略显笨拙。而且,实际生活中很多问题都是非线性**的,不可能使用全局限性模型来拟合任何数据。

  一种可行的方法是将数据集切分成很多份易建模的数据,然后再利用线性回归技术来建模。如果首次切分之后仍然难以拟合线性模型就继续切分。

  决策树是一种贪心算法,它要在给定时间内做出最佳选择,但是并不关心能否达到全局最优

 

CART(classification and regression trees,分类回归树)

之前使用过的分类树构建算法是ID3ID3决策树学习算法是以信息增益为准则来选择划分属性。ID3的做法是每次选取当前最佳的特征来分割数据,并按照该特征的所有可能取值来切分。也就是说,如果一个特征有4种取值,那么数据将被切成4份。一旦按某特征切分后,该特征在之后的算法执行过程中将不会再起作用,所以所以有观点认为这种切分方式过于迅速。另外一种方法是二元切分法,即每次把数据集切成两份。如果数据的某特征值等于切分所要求的值,那么这些数据就进入树的左子树,反之则进入树的右子树。

  ID3算法还存在另一个问题,它不能直接处理连续性数据。只有事先将连续特征转换成离散型,才能在ID3算法中使用。

  CART算法使用二元切分来处理连续型变量。对CART稍作修改就可以处理回归问题。CART决策树使用“基尼指数”来选择划分属性,基尼值是用来度量数据集的纯度

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
from numpy import *

def loadDataSet(fileName): #general function to parse tab -delimited floats
dataMat = [] #assume last column is target value
fr = open(fileName)
for line in fr.readlines():
curLine = line.strip().split('\t')
fltLine = map(float,curLine) #map all elements to float()
dataMat.append(fltLine)
return dataMat

def plotBestFit(file): #画出数据集
import matplotlib.pyplot as plt
dataMat=loadDataSet(file) #数据矩阵和标签向量
dataArr = array(dataMat) #转换成数组
n = shape(dataArr)[0]
xcord1 = []; ycord1 = [] #声明两个不同颜色的点的坐标
#xcord2 = []; ycord2 = []
for i in range(n):
xcord1.append(dataArr[i,0]); ycord1.append(dataArr[i,1])
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(xcord1, ycord1, s=30, c='green', marker='s')
#ax.scatter(xcord2, ycord2, s=30, c='green')
plt.xlabel('X1'); plt.ylabel('X2');
plt.show()

def binSplitDataSet(dataSet, feature, value): #该函数通过数组过滤方式将数据集合切分得到两个子集并返回
mat0 = dataSet[nonzero(dataSet[:,feature] > value)[0],:][0]
mat1 = dataSet[nonzero(dataSet[:,feature] <= value)[0],:][0]
return mat0,mat1

def regLeaf(dataSet): #建立叶节点函数,value为所有y的均值
return mean(dataSet[:,-1])

def regErr(dataSet): #平方误差计算函数
return var(dataSet[:,-1]) * shape(dataSet)[0] #y的方差&times;y的数量=平方误差

def chooseBestSplit(dataSet, leafType=regLeaf, errType=regErr, ops=(1,4)): #最佳二元切分方式
tolS = ops[0]; tolN = ops[1] #tolS是容许的误差下降值,tolN是切分的最少样本数
#如果剩余特征值的数量等于1,不需要再切分直接返回,(退出条件1)
if len(set(dataSet[:,-1].T.tolist()[0])) == 1:
return None, leafType(dataSet)
m,n = shape(dataSet)
#the choice of the best feature is driven by Reduction in RSS error from mean
S = errType(dataSet) #计算平方误差
bestS = inf; bestIndex = 0; bestValue = 0
for featIndex in range(n-1):
#循环整个集合
for splitVal in set(dataSet[:,featIndex]): #每次返回的集合中,元素的顺序都将不一样
mat0, mat1 = binSplitDataSet(dataSet, featIndex, splitVal) #将数据集合切分得到两个子集
#如果划分的集合的大小小于切分的最少样本数,重新划分
if (shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN): continue
newS = errType(mat0) + errType(mat1) #计算两个集合的平方误差和
#平方误差和newS小于bestS,进行更新
if newS < bestS:
bestIndex = featIndex
bestValue = splitVal
bestS = newS
#在循环了整个集合后,如果误差减少量(S - bestS)小于容许的误差下降值,则退出,(退出条件2)
if (S - bestS) < tolS:
return None, leafType(dataSet)
mat0, mat1 = binSplitDataSet(dataSet, bestIndex, bestValue) #按照保存的最佳分割来划分集合
#如果切分出的数据集小于切分的最少样本数,则退出,(退出条件3)
if (shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN):
return None, leafType(dataSet)
#返回最佳二元切割的bestIndex和bestValue
return bestIndex,bestValue

def createTree(dataSet, leafType=regLeaf, errType=regErr, ops=(1,4)):#assume dataSet is NumPy Mat so we can array filtering
feat, val = chooseBestSplit(dataSet, leafType, errType, ops) #采用最佳分割,将数据集分成两个部分
if feat == None: return val #递归结束条件
retTree = {} #建立返回的字典
retTree['spInd'] = feat
retTree['spVal'] = val
lSet, rSet = binSplitDataSet(dataSet, feat, val) #得到左子树集合和右子树集合
retTree['left'] = createTree(lSet, leafType, errType, ops) #递归左子树
retTree['right'] = createTree(rSet, leafType, errType, ops) #递归右子树
return retTree

 

mian.py

全文 >>

系统设计——登录系统

1.认证方式

系统的常用的认证方式如下:账号密码(Basic Auth),OAuth2.0,SAML,OIDC,LDAP等

1.OAuth2.0 是一种授权协议,旨在允许应用程序安全访问资源,而不是用来验证用户的身份。

它通常用于授权流程,以获得对受保护资源的访问权限。不兼容oauth1.0.允许第三方应用代表用户获得访问权限。

可以作为web应用、桌面应用和手机等设备提供专门的认证流程。例如,用qq账号登录豆瓣、美团、大众点评;用支付宝账号登录淘宝、天猫等。参考:各开放平台账号登录API对接文档

2.SAML的全称是Security Assertion Markup Language, 是由OASIS制定的一套基于XML格式的开放标准,用在身份提供者(IdP)和服务提供者 (SP)之间交换身份验证和授权数据。

SAML的一个非常重要的应用就是基于Web的单点登录(SSO)。

3.OpenID Connect (OIDC) 是在 OAuth 2.0 的基础上构建的身份验证协议。

OIDC 添加了身份验证层,允许客户端验证用户的身份,并获取有关用户的附加信息。

还有其他的一些认证方式我们可以在Postman的authorization中查看

2.验证

1.人机校验

常用的人机校验有cloudflare,reCAPTCHA等

全文 >>

特征预处理——特征缩放

特征缩放****(Feature Scaling)是一种将数据的不同变量或特征的方位进行标准化的方法。

在某些比较和评价的指标处理中经常会用到,去除数据的单位限制,将其转化为无量纲(数量级)的纯数值,便于不同单位或量级的指标能够进行比较和加权。

特征缩放的好处:

参考:标准化的好处及常见处理方法

  1. 提升模型的收敛速度

2.提升模型的精度

3.深度学习中数据归一化可以防止模型梯度爆炸。

需要特征缩放的模型:

参考:哪些机器学习模型需要归一化

概率模型(树形模型)不需要归一化,因为它们不关心变量的值,而是关心变量的分布和变量之间的条件概率,如决策树、RF(随机森林)、朴素贝叶斯、XGBoost、lightGBM、GBDT

而像Adaboost、SVM(支持向量机)、LR(线性回归、逻辑回归)、KNN、KMeans、神经网络(DNN、CNN和RNN)、LSTM之类的最优化问题就需要归一化

特征缩放的方法:

常用的特征缩放的方法有归一化、标准化、正态化等。参考:2(1).数据预处理方法

选择建议:

全文 >>

特征预处理——特征选择和特征理解

1.数据可视化

1.单变量可视化

参考:从kaggle房价预测看探索性数据分析的一般规律

查看pandas某列的统计指标

1
2
3
4
5
6
7
8
9
10
11
12
13
# 描述性统计
print(train_data['SalePrice'].describe())

count 1460.000000  # 行数
mean 180921.195890  # 平均值
std 79442.502883  # 标准差
min 34900.000000  # 最小值
25% 129975.000000  # 第1四分位数,即第25百分位数
50% 163000.000000  # 第2四分位数,即第50百分位数
75% 214000.000000  # 第3四分位数,即第75百分位数
max 755000.000000  # 最大值
Name: SalePrice, dtype: float64

使用displot函数可以绘制直方图,bins越大,横坐标的精度越大

1
2
3
4
5
6
7
8
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

sns.displot(train_data['SalePrice'], bins=100)
plt.show()

可以看到数据呈现偏态分布

2.双变量关系可视化

使用scatterplot函数绘制散点图,查看2个数值型(numerical)变量的关系

1
2
3
4
5
6
7
8
9
10
11
import matplotlib.pyplot as plt
import seaborn as sns

# 地上居住面积/房价散点图
sns.scatterplot(y=train_data['SalePrice'], x=train_data['GrLivArea'])
plt.show()
# 或者
data = pd.concat([train_data['SalePrice'], train_data['GrLivArea']], axis=1)
data.plot.scatter(x='GrLivArea', y='SalePrice', ylim=(0, 800000))
plt.show()

可以看出面积越大的房子,价格越高

全文 >>