个人博客


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

读过的书

发表于 2018-11-26 | 分类于 书

引言

本篇主要记录自己看过的书,督促自己平时多多的读书啊!

《假如我有时光机》-村上春树

2018-11-26
这本书是村上春树写的,主要描写了作者在全球旅游去过的国家和城市。这是我第一次读村上春树的书,整本书看起来还是比较吸人眼球的,同时本书篇幅也不是很长。从作者的文笔中,可以感受到作者是一个待人应该很和善,同时也非常有礼貌的一个作者。通过阅读此书,不单单能够感受到作者去过的地方,也能够感受到别人在旅行中收到的感受。对于自己也是一种心理上面的成长。书中第一章写到了美国波士顿,特别是里面的查尔斯河,读完之后,有很强烈的冲动去美国玩了。应该是最近两三年的计划中。

《局外人》 -加缪

2018-11-27~2018-12-4
这本书主要讲述了一个杀了人的罪犯,最后被判处死刑的故事。判处死刑的原因并不是因为他杀了一个人,而是因为他在母亲的葬礼上面没有哭,还有在服丧期间干了一些在社会上认为不应该做的事情。比如看滑稽电影,跟女友做爱以及主人公不信上帝等。这些与社会上不同的事情竟然导致法官判处主角死刑。我们跳脱出来来看整个事情,会发现整个法律在执行的过程中,会强烈的加上社会倾向,即社会上认为你这个人格格不入,会导致你在法律上处于一个非常不利的地步。这本书最震撼我的事书的最后,主角主动放弃了上诉的机会,面对自己的死亡。如果人人都说你做错了,那么到底是你真的做错了,还是这个世界错了呢?

《逻辑学导论》 -欧文·M·柯丕, 卡尔·科恩

2018-12-5~

《高效人士的七个习惯》

2018-12-29~

读过的技术书籍

发表于 2018-11-16 | 分类于 书

书籍

都说书籍是人类进步的阶梯,现在这篇博客就是记录下我个人梯子的组成,主要是技术相关的.隔一段时间会更新一次,因为梯子一直在增长,哈哈.

Hands-On Machine Learning with Scikit-Learn and TensorFlow

这本书主要是通过scikit-learn工具包来讲解如何使用常用的机器学习算法以及机器学习算法在平常的工作中的应用流程.深度学习主要是通过tensorflow来进行讲解.

Andrew Ng 斯坦福 cs229机器学习讲义

想要入门机器学习的同学,强烈建议学一学Andrew Ng的这么课,最好把里面的数学公式都自己推一遍,我自己推完这些数学公式之后,对于机器学习算法中原理有了很清晰的认识.

《mysql必知必会》

阅读时间:2019-4-7~2019-4-9
感想:这几天看完了mysql必知必会,其实基本上mysql的语法都会,只是为了能够看看还有什么地方自己不太知道的。总体来说,这本书对于初学者比较适合,按着里面的内容手敲一遍例子。掌握mysql的使用是没有问题的。

《图解tcp-ip 第五版》

阅读时间:2019-4-9
感想:

《effective java 第三版》 英文

阅读时间:2019-4-10
感想:

统计学知识

发表于 2018-11-02 | 分类于 机器学习 , 统计学

统计学相关知识

在平常的机器学习应用中,我们首先要做的事情就是分析数据.分析数据有很多种方法,而且其中很多方法都是统计学中的内容.本篇blog主要记录我认为平常经常能够用到的统计学内容.

箱线图(box)

箱线图主要是用来分析数据中的异常值,在数据分析中非常有用.同时它也能够用来分析某一个特征跟预测值之间的关系,参考.如下图所示

在python的seaborn包中画箱线图主要是调用boxplot函数,具体的使用方法可以查看相关文档.

1
2
3
import seaborn as sns
sns.boxplot(x,y,data)

svm原理介绍

发表于 2018-10-18 | 分类于 machine learning

支持向量机

这篇博客主要介绍如何推导svm算法。写这篇博客主要是最近在学习svm算法,想着合上书,自己推导一遍算法的原理,发现还是有很多需要思考的地方。
其实一般推导机器学习算法,是有一个模式的。

  1. 定义模型,这里模型理解为如何定义公式
  2. 选择损失函数
  3. 采用优化算法求损失函数的最小值
  4. 推导完毕

比如拿逻辑回归算法举例:

  1. 定义模型,即选取sigmoid函数
  2. 定义损失函数
  3. 采用最大梯度下降算法求损失函数的最小值
  4. 得到算法的w和b

但是svm的推导基本上没有怎么提损失函数的内容,大家等会可以在这篇博客中看到如何推导svm算法

判别函数

上式是SVM的判别函数,其中函数g如下所示:

即$g(z)$的输出为1时,判别为正例;输出为-1时,判别为反例。

函数间隔和几何间隔(Functional and geometric margins)

函数间隔

对于某一个训练样本$(x^(i), y^(i))$定义函数间隔如下式:

分析函数间隔公式,可以得出如下的结论.当$y^{(i)}=1$时,则$w^T+b>0$,所以$g(z) = 1$;当$y^{(i)}=-1$时,则$w^T+b<0$,所以$g(z) = -1$.所以函数间隔对于判别样本的类别是有作用的.
但是,当我们将$w,b$扩大两倍时,函数函数间隔扩大两倍,但是对于$g(z)$并没有什么变化.即下式成立

所以更大的函数间隔并不一定比小的函数间隔的置信度大.由此引出了几何间隔

几何间隔

针对几何间隔,我们考虑二维平面,如下图所示:

图中的斜线是对应于参数$(w,b)$的决策分隔线.注意$w$是垂直于决策线的,即$w$是决策线的法向量.

证明如下:
设$x_0,x_1$是直线$w^T+b=0$上不同的两个点,则有下式成立

两式相减的$w^T(x_0 - x_1) = 0$,而其中$x_0 - x_1$是直线$w^T+b=0$的方向向量,所以w是法向量.

图中$\gamma^{(i)}$是A点对应的几何间隔.设A点为$x^{(i)}$,而向量$w/{\left|w\right|}$是法向量上的单位向量.因此得到B点为$x^{(i)} - \gamma^{(i)}\cdot w/{\left|w\right|}$,又因为B点在分离平面上,所以下式成立:

从而得到下式:

如果A点在B点的另外一侧,则B点可以表示为下式:

综合两种情况,得到

具体的公式推导过程中,并没有完全限制在二维平面上(虽然开始展示的图像是二维平面上的),所以对于高维平面也是得到上述公式.
几何间隔反应了样本到分离面的距离,直观上最小的几何间隔越大越好.并且几何间隔中的参数$w,b$可以随意的进行尺度变换而不影响几何间隔的大小(这是因为几何间隔的式子中除以了w的二范数).同时当$\left|w\right|=1$时,几何间隔就等于函数间隔.
定义

即$\hat{\gamma}$和${\gamma}$分别是函数间隔和几何间隔的最小值.

最优间隔分类器

通过上面的函数间隔和几何间隔,我们自然能够想到优化目标如下式所示:

即在满足所有样本的几何间隔都大于最小几何间隔的情况下,求使得几何间隔最大的参数$w,b$
我们可以将上述优化公式转变成用函数间隔进行表达,如下式所示:

上述两个优化问题为什么等价?因为$\gamma={\frac {\hat\gamma} {\left|w\right|}}$.针对优化公式(1.2),即求取几何间隔最大,同时在约束不等式两边同时除以$\left|w\right|$,即得所有的几何间隔都大于最小的几何间隔.这即等价于优化公式(1.1)

由于参数$w,b$进行尺度变化,所以我们可以固定函数间隔等于1,即$\hat\gamma=1$
最终将优化公式化简为下式:

针对这个优化公式,即满足不等式的条件下,求取二次函数的最小值,虽然可以采用优化算法求取此最优值.但是我们下面介绍拉格朗日对偶来进行求取,第一求取最优值会变得更加简单,第二能够使用核函数.

拉格朗日对偶(Lagrange duality)

拉格朗日对偶主要是将优化公式转变为其对偶形式,具体的推导过程可以参考Andrew Ng cs229课程中的内容.

再次求解最优间隔分类器

通过拉格朗日对偶,将SVM的优化目标转变为对偶形式,从而得到参数$w,b$

Gaussian Discriminant Analysis and Logistic Regression

发表于 2018-09-16 | 分类于 机器学习

高斯判别分析和逻辑回归算法的关系

最近一直在看Andrew Ng的cs229那门课的讲义,看到高斯判别分析模型和逻辑回归算法的关系那一部分,自己采用贝叶斯后验概率也证明了两者之间的关系,证明不难,本来打算记录一下的。在网上看到有个外国人写的更好,那我就把他写的直接翻译过来了。当然文章中也加入了在网上看到的其他资料和自己的一些思考。
原文

判别模型和生成模型

有很多方式可以对机器学习算法进行分类,比如:监督/非监督,回归/分类,等等。还有一种方式用判别模型(Discriminative model)和生成模型(Generative model)进行区分.本篇文章,我们将会讨论高斯判别分析(Gaussian Discriminant Analysis )模型和逻辑回归(Logistic Regression)之间的关系,这也体现了判别模型和生成模型之间的关系。
判别模型是求$p(y|x)$.在分类问题中,判别模型是直接寻找能够将不同类的数据分开的超平面或者称之为决策边界。有很多常用的机器学习算法属于判别模型,比如:逻辑回归,SVM,神经网络等等。另一方面,生成模型是求取$p(x|y)$和$p(y)$.这意味着,在分类问题中,生成模型给出了每个类的概率分布,给出了数据是如何生成的。也即生成(generative)这个词的意思.生成模型依赖贝叶斯公式计算后验概率$p(y|x)$.像朴素贝叶斯,高斯判别分析等都属于生成模型。

在实际使用中,判别模型要比生成模型用的更多,原因很多。比如:判别模型更加灵活,更加鲁棒,当对模型做出错误的假设时,模型表现的也不是很敏感。而生成模型需要我们定义数据的先验概率,即数据分布,在很多时候这是非常有困难和挑战的。然后,生成模型也有它的优势,比如:相比于判别模型,生成模型对于数据有更多的先验信息。这导致如果我们对于数据的假设是正确的,那么生成模型在少量数据下也能够表现的更好。

GDA和逻辑回归

接下来我将要证明,GDA(Gaussian Discriminant Analysis)如何最终推导出逻辑回归,从这个推导中也可以看出采用逻辑回归的道理。
对于二分类问题,GDA假设类别服从伯努利分布,数据服从多元高斯分布,如下:

具体的数学公式如下:

而采用GDA就是求取后验概率,我们可以证明如下等式成立:

在公式中可以看到,GDA关于类别1的后验概率就是逻辑回归的sigmoid函数,这里$\theta$就是关于参数$\phi,\mu_0,\mu_1,\sum$的函数
接下来进行证明:

我们接下来带入概率公式,计算$\frac{1}{1 + \frac{p(x|y=0)\times{p(y=0)}}{p(x|y=1)\times{p(y=1)}}}$,计算过程如下,主要是涉及一些log和exp的转换:

在公式的最后,我们令$x_0=1$,至此我们得到了$\theta^Tx$,即如下式:

$\theta$向量的值如下:

关系说明

可以看出,从GDA可以推导出逻辑回归,但是反过来是不成立的。即如果$p(y|x)$是一个逻辑回归函数并不能推导出$p(x|y)$是一个多元的高斯分布。这说明GDA模型比逻辑回归模型具有更强的假设。事实上,如果$p(x|y)$是指数分布族(Exponential Family,比如高斯分布,泊松分布)中的一种,那么其后验概率就是逻辑回归。由此我们也得到一个为什么逻辑回归使用的更加广泛的原因,因为逻辑回归是一种非常通用,健壮的算法,适用于许多基本假设。另一方面,GDA以及一般的生成模型做出了更强的假设,因此对于非高斯或某些未定义分布数据来说并不理想。
特别的,当$p(x|y)$是高斯分布(类别之间具有相同的协方差)时,则GDA是渐进有效的(首先搞清楚什么叫有效性,有效性是指在所有的无偏估计方法里,某种方法的估计量的方差是最小的,则该种估计方法就是有效的,比如古典假定的OLS(最小二乘算法)估计。渐近有效是指该种估计方法在中小样本时可能不是最有效的,但随着样本数的增加,慢慢变得有效(没有其它无偏估计方法可以得到更小的方差),这就称为渐近有效,比如正态分布下线性模型的最大似然估计)。非正式地说,当训练集数目很大时,没有模型能显著地比GDA更好(即模型准确估计$p(y|x)$的程度).如果数据服从正态分布,则GDA要比逻辑回归表现的更好,更近一步,即使对于比较小的训练集,我们也总是认为GDA要表现的更好。
假设有一个一维训练集,包含一些正样本和负样本,如下图x轴的叉和圈,设叉为0,圈为1,用GDA对两类样本分别拟合高斯概率密度函数p(x|y=0)和p(x|y=1),如下图的两个钟形曲线。沿x轴遍历样本,在x轴上方画出相应的p(y=1|x)。如选x轴靠左的点,那么它属于1的概率几乎为0,p(y=1|x)=0,两条钟形曲线交点处,属于0或1的概率相同,p(y=1|x)=0.5,x轴靠右的点,输出1的概率几乎为1,p(y=1|x)=1。最终发现,得到的曲线和sigmoid函数曲线很相似。

也就是说,当使用GDA模型时,p(x|y)属于高斯分布,计算p(y|x)时,几乎能得到和logistic回归中使用的sigmiod函数一样的函数,但实际上还是存在本质区别。

在Andrew Ng的cs229采用两种方法可以推导出逻辑回归

  1. 通过指数分布族来推导。
  2. 通过生成学习假设先验概率分布的方式进行推导。

如何选择两种模型

由上面的分析可以知道,GDA比逻辑回归有更多的前置假设。当数据服从或大致服从正态分布时,GDA会具有更高的拟合度,因为GDA利用了更多的信息构建模型。但是当数据不服从正态分布时,那么逻辑回归更有效,因为它做出更少的假设,构建的模型更加强壮,更加具有鲁棒性。生成学习还有另外的一个好处,就是可以使用比判别学习模型使用更少的数据构建出强壮的模型。

总结

通过推导,我们可以看到很多算法内在都是存在某种联系的,理解算法之间的关系对于我们理解算法以及选择什么算法都是有很多的帮助的。

参考文章

  1. Gaussian Discriminant Analysis and Logistic Regression

jupyter notebook使用

发表于 2018-09-15 | 分类于 python

jupyter notebook

Jupyter notebook, 前身是 IPython notebook, 它是一个非常灵活的工具,有助于帮助你构建很多可读的分析,你可以在里面同时保留代码,图片,评论,公式和绘制的图像。
这篇文章主要是记录下jupyter notebook使用过程中一些常用的内容和技巧,包括一些magic使用

快捷键

windows上,Ctrl + Shift + P可以调出快捷键的帮助信息,所有的快捷键都能够看到。掌握快捷键能够帮助我们更好的使用jupyter notebook

Jupyter Magic Commands

  1. %matplotlib inline

如果想在jupyter中画图,可以添加如下代码,则图像就能够进行显示

1
%matplotlib inline

2. Timing

对于计时有两个十分有用的魔法命令:%%time 和 %timeit. 如果你有些代码运行地十分缓慢,而你想确定是否问题出在这里,这两个命令将会非常方便。

%%time 将会给出cell的代码运行一次所花费的时间。

1
2
3
4
%%time
import time
for _ in range(1000):
time.sleep(0.01)# sleep for 0.01 seconds

%timeit 使用Python的timeit模块,它将会执行一个语句100,000次(默认情况下),然后给出运行最快3次的平均值。

1
2
import numpy
%timeit numpy.random.normal(size=100)

运行文件

Quartz与Spring结合使用及集群配置

发表于 2018-09-15 | 分类于 Spring

Quartz与Spring结合使用及集群配置

本文的原文在我个人的CSDN上。是在2017年的时候由于工作上面需要用到在集群环境中使用调度,采用了Quartz实现,当时进行了记录。不过现在我写博客主要是在个人站点上,所以就把之前的博客部分搬移过来了。
本文代码github地址

quartz介绍

quartz是进行任务调度执行的框架,相对于Java中线程池调度以及Spring自带注解的调度方法,有以下几个有点:

  1. 能够支持上千上万个调度任务的执行
  2. 任务调度方式较为灵活
  3. 支持集群

运行环境

  1. quartz版本:2.2.1,这是quartz最新的版本,其他版本可能跟此版本有一定差异
  2. 操作系统centos7,我在vmware中搭建了三台独立的虚拟机
  3. JDK8
  4. 数据库:mysql 5.7.18
  5. tomcat8

工程目录结构

工程目录结构如下,采用Idea IDE

文件说明:
resources下是各种配置资源,create-schema.sql用于创建任务表,tables_mysql_innodb.sql用于创建quartz集群运行需要的表,共有十一张表。quartz_properties是quartz的配置

主要配置文件内容

配置文件中都有每个配置项详细的说明,我这里就只给出具体的配置内容
spring配置文件有两个,分别为applicationContext.xml和spring-mvc.xml
applicationContext.xml文件如下

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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<context:component-scan base-package="com.ll.*"/>

<!-- 启用@Aspect支持 -->
<aop:aspectj-autoproxy/>
<!-- 加载数据库配置 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName">
<value>${jdbc.driver}</value>
</property>
<property name="url">
<value>${jdbc.url}</value>
</property>
<property name="username">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
<property name="initialSize">
<value>${jdbc.initialSize}</value>
</property>
<property name="maxActive">
<value>${jdbc.maxActive}</value>
</property>
<property name="maxIdle">
<value>${jdbc.minIdle}</value>
</property>
<property name="maxWait">
<value>${jdbc.maxWait}</value>
</property>
</bean>

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="fetchSize">
<value>${jdbc.jdbcTemplate.fetchSize}</value>
</property>
</bean>
<!-- 访问数据库方式 -->
<bean id="jdbcDao" class="com.dexcoder.dal.spring.JdbcDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>

<!-- 配置quartz调度器 -->
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="dataSource" ref="dataSource" />
<!--可选,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了 -->
<property name="overwriteExistingJobs" value="true" />
<!--必须的,QuartzScheduler 延时启动,应用启动完后 QuartzScheduler 再启动 -->
<property name="startupDelay" value="3" />
<!-- 设置自动启动 -->
<property name="autoStartup" value="true" />
<!-- 把spring上下 文以key/value的方式存放在了quartz的上下文中了 -->
<property name="applicationContextSchedulerContextKey" value="applicationContext" />
<!-- scheduler的名称 -->
<property name="schedulerName" value="ClusterScheduler" />
<property name="configLocation" value="classpath:quartz.properties" />
<!-- <property name="quartzProperties"> -->
<!-- <props> -->
<!-- <prop key="org.quartz.scheduler.instanceName">ClusterScheduler</prop> -->
<!-- <prop key="org.quartz.scheduler.instanceId">AUTO</prop> -->
<!-- 线程池配置 -->
<!-- <prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop> -->
<!-- <prop key="org.quartz.threadPool.threadCount">20</prop> -->
<!-- <prop key="org.quartz.threadPool.threadPriority">5</prop> -->
<!-- JobStore 配置 -->
<!-- <prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop> -->

<!-- 集群配置 -->
<!-- <prop key="org.quartz.jobStore.isClustered">true</prop> -->
<!-- <prop key="org.quartz.jobStore.clusterCheckinInterval">15000</prop> -->
<!-- <prop key="org.quartz.jobStore.maxMisfiresToHandleAtATime">1</prop> -->

<!-- <prop key="org.quartz.jobStore.misfireThreshold">120000</prop> -->

<!-- <prop key="org.quartz.jobStore.tablePrefix">QRTZ_</prop> -->
<!-- </props> -->
<!-- </property> -->
</bean>
</beans>

spring-mvc.xml内容如下:

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
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<context:component-scan base-package="com.ll.*" />

<bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1" />
<property name="ignoreAcceptHeader" value="true" />
<property name="mediaTypes">
<map>
<entry key="json" value="application/json;charset=UTF-8" />
<entry key="xml" value="application/xml;charset=UTF-8" />
<entry key="rss" value="application/rss+xml;charset=UTF-8" />
</map>
</property>
<property name="defaultViews">
<list>
</list>
</property>
</bean>

<bean id="velocityConfig"
class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
<property name="resourceLoaderPath" value="/WEB-INF" />
<property name="configLocation" value="classpath:velocity.properties" />
</bean>

<bean id="viewResolver"
class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
<!-- <property name="order" value="2"/> -->
<property name="suffix" value=".vm" />
<property name="prefix" value="/"/>
<!-- <property name="exposeSpringMacroHelpers" value="true"/> -->
<!-- <property name="requestContextAttribute" value="rc"/> -->
<property name="contentType" value="text/html;charset=UTF-8" />
</bean>

</beans>

Quartz配置文件为quartz.properties,内容如下:

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
81
82
83
84
85
86
87
88
89
90
#配置参数详解,查看http://haiziwoainixx.iteye.com/blog/1838055
#============================================================================
# Configure Main Scheduler Properties
#============================================================================
# 可为任何值,用在jdbc jobstrore中来唯一标识实例,但是在所有集群中必须相同
org.quartz.scheduler.instanceName: MyClusteredScheduler
#AUTO即可,基于主机名和时间戳来产生实例ID
#集群中的每一个实例都必须有一个唯一的"instance id",应该有相同的"scheduler instance name"
org.quartz.scheduler.instanceId: AUTO
#禁用quartz软件更新
org.quartz.scheduler.skipUpdateCheck: true

#============================================================================
# Configure ThreadPool 执行任务线程池配置
#============================================================================
#线程池类型,执行任务的线程
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
#线程数量
org.quartz.threadPool.threadCount: 10
#线程优先级
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

#============================================================================
# Configure JobStore 任务存储方式
#============================================================================

org.quartz.jobStore.misfireThreshold: 60000
#可以设置两种属性,存储在内存的RAMJobStore和存储在数据库的JobStoreSupport
#(包括JobStoreTX和JobStoreCMT两种实现JobStoreCMT是依赖于容器来进行事务的管理,而JobStoreTX是自己管理事务)
#这里的属性为 JobStoreTX,将任务持久化到数据中。
#因为集群中节点依赖于数据库来传播 Scheduler 实例的状态,你只能在使用 JDBC JobStore 时应用Quartz 集群。
#这意味着你必须使用 JobStoreTX 或是 JobStoreCMT 作为 Job 存储;你不能在集群中使用 RAMJobStore。
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX

#JobStoreSupport 使用一个驱动代理来操作 trigger 和 job 的数据存储
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#若要设置为true,则将JobDataMaps中的值当作string
org.quartz.jobStore.useProperties=false
#对应下方的数据源配置,与spring结合不需要这个配置
#org.quartz.jobStore.dataSource=myDS
#org.quartz.jobStore.tablePrefix=QRTZ_

#你就告诉了Scheduler实例要它参与到一个集群当中。这一属性会贯穿于调度框架的始终,用于修改集群环境中操作的默认行为。
org.quartz.jobStore.isClustered=true
#属性定义了Scheduler实例检入到数据库中的频率(单位:毫秒)。默认值是 15000 (即15 秒)。
org.quartz.jobStore.clusterCheckinInterval = 20000

#这是 JobStore 能处理的错过触发的 Trigger 的最大数量。
#处理太多(超过两打) 很快会导致数据库表被锁定够长的时间,这样就妨碍了触发别的(还未错过触发) trigger 执行的性能。
org.quartz.jobStore.maxMisfiresToHandleAtATime = 1
org.quartz.jobStore.misfireThreshold = 120000
org.quartz.jobStore.txIsolationLevelSerializable = false

#============================================================================
# Other Example Delegates 其他的数据库驱动管理委托类
#============================================================================
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.DB2v6Delegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.DB2v7Delegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.DriverDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.HSQLDBDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.MSSQLDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PointbaseDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.WebLogicDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.WebLogicOracleDelegate

#============================================================================
# Configure Datasources 数据源配置,与spring结合不需要这个配置
#============================================================================

#org.quartz.dataSource.myDS.driver: com.mysql.jdbc.Driver
#org.quartz.dataSource.myDS.URL: jdbc:mysql://localhost:3306/quartz
#org.quartz.dataSource.myDS.user: root
#org.quartz.dataSource.myDS.password: 123
#org.quartz.dataSource.myDS.maxConnections: 5
#org.quartz.dataSource.myDS.validationQuery: select 0

#============================================================================
# Configure Plugins
#============================================================================
#当事件的JVM终止后,在调度器上也将此事件终止
#the shutdown-hook plugin catches the event of the JVM terminating, and calls shutdown on the scheduler.
org.quartz.plugin.shutdownHook.class: org.quartz.plugins.management.ShutdownHookPlugin
org.quartz.plugin.shutdownHook.cleanShutdown: true

#记录trigger历史的日志插件
#org.quartz.plugin.triggHistory.class: org.quartz.plugins.history.LoggingJobHistoryPlugin

运行

当按照此项目配置完成之后,将项目打包成war包,然后在一台centos下启动项目,添加任务,之后再另一台centos下也运行此war包。为了简单起见,这里添加的任务仅仅是输出任务的详细信息,并没有其他动作。在两台机器的catalina.out中可以看到输出的结果,可以看到任务可以负载均衡的运行在不同的机器上。

如何动态的查看catalina.out中的内容,可以用tail -f来查看,能够实时看到文件的变化

python知识点

发表于 2018-09-07 | 分类于 python

都是关于python3的内容

Python知识点

这里主要是记录下我平常编程中用到,但是不太清楚地知识点,仅仅作为一个记录使用

python基本类型

  1. Number(数字)
  2. String(字符串)
  3. List(列表)
  4. Tuple(元组)
  5. Set(集合)
  6. Dictionary(字典)

不可变数据:Number(数字)、String(字符串)、Tuple(元组);
可变数据:List(列表)、Dictionary(字典)、Set(集合)。
使用type()可以查看变量的类型,用isinstance()也可以查看。区别:

  • type()不会认为子类是一种父类类型
  • isinstance()认为子类是一种父类类型

如下代码所示:

1
2
3
4
5
6
7
8
9
10
class A:
pass

class B(A):
pass

isinstance(A(), A) # returns True
type(A()) == A # returns True
isinstance(B(), A) # returns True
type(B()) == A # returns False

Number

Python3中Number包括:int,float,bool,complex.注意只有一种整数类型int,表示长整型。

numpy相关

维度问题

注意下面的col_r1和col_r2的输出以及对应维度

1
2
3
4
5
6
7
8
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
print(a)
col_r1 = a[:, 1]
col_r2 = a[:, 1:2]
print(col_r1)
print(col_r1.shape)
print(col_r2)
print(col_r2.shape)

numpy数组访问

注意这里使用数组索引来访问numpy数组。这里可以看成[[[0, 1, 2], [0, 1, 0]]]中(0,0),(1,1),(2,0)看成三对

1
2
3
import numpy as np
a = np.array([[1,2], [3, 4], [5, 6]])
print(a[[0, 1, 2], [0, 1, 0]]) # Prints "[1 4 5]"

  1. numpy中有mat和array,都可以用来表示多维数据。如果一个

线性回归算法

发表于 2018-09-05 | 分类于 机器学习

线性回归算法

注:本文所有代码和数据均在个人github下click me

回归算法一般是针对预测是连续的情况下,对于预测值是离散的,采用的算法是分类算法。线性回归算法包括很多种变形,这里提到的线性回归算法是其中的几种典型算法。在实际应用中,我们采用线性算法可以预测商品的价格,预测房子的房价等等,虽然线性回归算法比较简单,但是在实际中还是有很多的使用的。

在机器学习中,我们要紧盯三件事情。第一,算法的损失函数;第二,采用什么求值算法求损失函数的最小值;第三,算法的评价指标

一般线性回归算法

一般的线性回归又叫做最小二乘算法,最小二乘是因为算法的损失函数是最小二乘的,损失函数如下:

其中$h_\theta(x^{(i)})$是算法针对数据的预测值,而$y^{(i)}$是数据的真实值,$m$表示训练数据的条数,而${\frac 12}$是为了此公式求导方便而加入的。而$\theta$是算法的参数,在这里就是线性回归的权重值。通过此公式我们可以得到,线性回归算法的损失函数就是针对每个样本计算预测值和真实值得差,然后将差求平方,之后将全体样本的差平方相加即得到损失函数。
针对损失函数,我们有两种算法可以求取损失函数的最小值。

梯度下降算法

梯度下降算法的一般形式:

这里写的是梯度下降算法的标量形式。这个公式描述了梯度下降算法是如何更新算法的参数的,其中$\alpha$是参数的更新步长。可以看到这里的关键是如何求取损失函数关于参数j的偏导数。
将损失函数带入到梯度下降算法,即公式$(1.2)$中,并且求导,可以得到下式:

我们重复的使用公式$(1.3)$直到达到收敛条件,即可以求得线性回归算法中的参数值。
从公式中,可以看到用真实值和预测值之间的差值来更新参数值,这种方式或者思想在很多的机器学习算法中可以看到,包括深度学习的后向传播算法。同时,可以看到每一次的迭代都要使用整个数据集。这种方式叫做批量梯度下降算法。还有一种方式可以求取$\theta$值,叫做随机梯度下降算法,算法如下:

从中我们可以看到,随机梯度下降算法每次采用一个训练样本取更新所有的参数值,注意那里的(for every j)。当训练样本很多时,相比于批量梯度下降算法,随机梯度下降算法能够更快的更新算法的参数值,并且能够更快的逼近损失函数的最小值。

代数解

我们将损失函数用向量表示,如下所示:

公式中的$X$表示训练数据的矩阵。因为损失函数是凸二次函数,所以只有一个最小值,所以导数为0的点就是损失函数的最小值。
具体的推导过程如下(主要利用了矩阵的迹运算):

令导数等于0,从而得到:

回归模型的概率解释

大家想过没有,为什么在线性回归模型里面选择最小二乘作为损失函数?接下来从概率的角度来解释选择最小二乘作为损失函数的原因。
首先,假设目标变量和输入数据存入如下的关系:

这里的$\epsilon^{(i)}$是误差项,包括模型未考虑到影响目标变量的因素和随机噪声。
接下来假设,误差项相互独立同分布,并且服从高斯分布(即正态分布)

为什么要假设误差项服从高斯分布? 第一是因为采用高斯分布,在数学上处理会比较简单;第二是因为根据中心极限定理,独立的随机变量的和,其总的影响接近高斯分布

误差项的概率密度函数为:

根据公式$(1.6)$和公式$(1.7)$,我们可以得出如下结论:

在公式中,$\theta$不是随机变量,而是实际存在的值,虽然我们不知道真实值是多少。$p(y^{(i)}|x^{(i)};\theta)$的含义是给定$x^{(i)}$,参数设定为$\theta$时,的概率密度。注意公式中用的分号。
数据的概率是由$p(\vec{y} | X;\theta)$给出的,而总的概率可以看成是在固定$\theta$时,关于$\vec{y}$的函数。换个角度,我们想要将这个函数明确的看成是关于$\theta$的函数,所以我们将其称作似然函数,从而我们得到关于$\theta$的似然函数:

似然(likelihood)和概率(probability)实际上是一个东西,但是似然函数是对参数$\theta$定义的,为了加以区分,使用了似然这一术语。我们可以说参数的似然,数据的概率,但不能说数据的似然,参数的概率。

极大似然估计就是选择$\theta$,使参数的似然函数最大化,也就是选择参数使得已有样本的出现概率最大。
因为$L(\theta)$是严格单调递增的,并且对数函数也是递增的,所以取对数,得到的$\theta$跟不取对象是一样的。

对数似然函数$\mathcal {l}(\theta)$:

最大化似然函数,就是最大化对数似然函数,即最小化

这个式子刚好是线性回归算法中采用的损失函数。总结一下,最小二乘回归模型刚好就是在假设了误差独立同服从正态分布后,得到的最大似然估计。同时注意到,正态分布中的方差$\sigma^2$的取值对模型并没有影响。

编程实现

代数解实现线性回归算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def standard_regression(x_arr, y_arr):
"""
这里直接采用代数解直接求取权重大小.这里有个条件是xTx的逆必须存在,
如果不存在,则直接返回
:param x_arr:
:param y_arr:
:return:
"""
x_mat = np.mat(x_arr)
y_mat = np.mat(y_arr).T
xTx = x_mat.T * x_mat
if np.linalg.det(xTx) == 0.0:
print("矩阵是奇异的,逆不存在")
return
ws = xTx.I * (x_mat.T * y_mat)
return ws

根据standard_regression函数可以直接求取算法的权重。然后根据权重就可以求得数据的预测结果,这里选择的数据在点我
画出的图像如下:

直线为拟合直线,散点是真实值。

随机梯度下降实现线性回归

由于代码篇幅比较长,所以可以直接上我的github上面看。代码

局部加权线性回归算法

每个点都对应一个不同的$\theta$,利用$\theta$计算预测值。
下面我们用刚才介绍的局部加权线性回归来拟合一下这个模型,简单回顾一下过程:
1.用高斯核函数计算出第i个样本处,其它所有样本点的权重W
2.用权重w对第i个样本作加权线性回归,得到回归方程,即拟合的直线方程
3.用刚才得到的经验回归直线计算出$x^i$处的估计值$y^i$
4.重复一至三步,得到每个样本点的估计值

同时,从计算公式中,可以看到对于每个点的预测值,需要利用所有的数据样本进行计算。如果数据量比较大,计算量就会是一个大问题。
相比于上面提到线性回归算法(参数算法),局部加权线性回归算法是非参数算法。

参数算法vs非参数算法

引用地址

参数算法:
如果我们对所要学习的问题有足够的认识,具备一定的先验知识,此时我们一般会假定要学习的目标函数f(x)或分布P(y|x)的具体形式。然后,通过训练数据集,基于ERM、SRM、MLE、MAP等学习策略,可以估计出f(x)或P(y|x)中含有的未知参数。一旦未知参数估计完毕,训练数据一般来说,就失去其作用了,因为这些估计出来的参数就是训练数据的浓缩。通过这种方式建立起来的模型就是参数模型。参数模型的一个很重要的特点是,如果对于模型的假设正确,那么只需要很少的训练数据就可以从假设空间中学出一个很好的模型。但是,如果模型的假设错误,那么无论训练的数据量有多大,甚至趋于无穷大,学出的模型都会与实际模型出现不可磨灭的偏差。感知机、逻辑斯特回归、高斯判别分析、朴素贝叶斯、线性支持向量机都属于参数模型。对于神经网络来说,当固定了隐层的数目以及每一层神经元的个数,它也属于参数模型。但由于隐层数目与每一层神经元个数的不确定性,很多时候,神经网络都被归类为半参数模型。
非参数算法:
当我们对所要学习的问题知之甚少,此时我们一般不会对潜在的模型做过多的假设。在面对预测任务的时候,我们通常会用上所有的训练数据。例如简单的核密度估计(KDE)的表达式中,就带有所有训练数据的信息。通过这种方式建立的模型就是非参数模型。非参数模型的一个很重要的特点就是:let the data speak for itself. 正因为如此,非参数模型的存储开销、计算开销都会比参数模型大的多。但是,由于不存在模型的错误假定问题,可以证明,当训练数据量趋于无穷大的时候,非参数模型可以逼近任意复杂的真实模型。这正是非参数模型诱人的一点。另外需要说明的一点是,非参数模型之所以叫做非参数,并不是因为模型中没有参数。实际上,非参数模型中一般会含有一个或多个超参数,外加无穷多个普通的参数。k近邻就是典型的非参数模型。

总结就是所谓参数学习算法它有固定的明确的参数,参数 一旦确定,就不会改变了,我们不需要在保留训练集中的训练样本。而非参数学习算法,每进行一次预测,就需要重新学习一组 , 是变化的,所以需要一直保留训练样本。

实际使用

这里采用的数据跟线性回归算法采用的相同。选取不同的k值,得到的拟合曲线如下图:

从图中可以看到,当k值较小时,对于训练数据有很好的拟合效果;当k值较大时(比如取1),对于训练数据拟合的效果不是很好。当然这都是针对训练数据,在实际使用中,我们更关注的是对于测试数据的效果如何。在实际中,我们可以将数据进行十倍交叉验证,选择最合适的k值。
从高斯公式中,我们从两个方面看。首先,我们固定k值,那么距离$x^{(i)}$较远的样本,其对应的权重相对较小;距离$x^{(i)}$较近的样本,其对应的权重相对较大,当x取$x^{(i)}$时,对应的权重为1。而如果我们固定x(即只看某一特定样本点),k取值较大时,此样本点对应的权重相对较大;k取值较小时,此样本点对应的权重相对较大。所以k可以控制算法选择$x^{(i)}$点附近有多少样本参与计算。

最上面的图是样本点,剩下三幅图都是针对样本点x=0.5,根据不同的k值,画出的x附近样本的权重变化。可以看到,当k取0.5时,当计算x=0.5时的预测值时,几乎所有的样本点都包括了;而当k=0.01时,仅仅取了x=0.5附近的点参与计算。如果k值取无穷大,那么w对于所有的点的权重都是1,那么局部加权线性回归就变成了普通的线性回归算法。

岭回归算法(Ridge Regression)

上面介绍的线性回归算法里面可以看到需要计算$X^TX$的逆,那么如果逆不存在呢?首先思考第一个问题,什么情况下,$X^TX$的逆不存在呢?

  1. X本身存在相关关系,即非满秩矩阵。比如其中两列是具有线性关系
  2. 如果特征列多余样本数量,那么$X^TX$也是非满秩的。

对于逆不存在的情况下,我们需要将原来的线性回归算法进行处理,使原先无法求逆的$X^TX$变成非奇异的。可以通过缩减的方式来处理这类问题,比如岭回归算法和LASSO算法。同时由于能够调整算法中权重的大小,能够防止线性回归算法的过拟合问题。

岭回归算法损失函数

通过改变$\lambda$的值,可以使得算法的方差和偏差之间达到平衡,增加$\lambda$,模型的方差减小而偏差增加。
对损失函数求取一阶导数,并另导数等于0,求得权重如下式:

在岭回归算法中$\lambda$的选择对于算法有很大的影响。下图展示了不同的$\lambda$的取值对于权重的影响,因为数据有八个特征,所以这里有八个权重。当$\lambda$较小时,权重的值跟采用常规的线性回归差不多;而当$\lambda$较大时,权重的值都会被调解的较小。

为了找到合适的$\lambda$值,我们在实践中往往会采用交叉测试来找到合适的$\lambda$值。

lasso回归算法(Least Absolute Shrinkage and Selection Operator)

从岭回归算法中,我们可以看到,算法防止过拟合主要是在损失函数中添加惩罚项。在岭回归中,惩罚项如下所示:

而在lasso回归算法中,惩罚项变成下式:

即将权重的平方和小于$\lambda$,替换为权重的绝对值和小于$\lambda$.进行了这个变化后,能够将权重缩小到0,而岭回归中无法将权重值缩小到0,只能接近0.

lasso回归算法损失函数

我们也可以结合岭回归算法和lasso的损失函数,构建新的损失函数。这就是弹性网络(ElasticNet)

逐步向前回归

LASSO计算复杂度相对较高,本部分稍微介绍一下逐步向前回归,他属于一种贪心算法,给定初始系数向量,然后不断迭代遍历每个系数,增加或减小一个很小的数,看看代价函数是否变小,如果变小就保留,如果变大就舍弃,然后不断迭代直到回归系数达到稳定。代码如下:

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
def run_stage():
x_arr, y_arr = load_data_set('./data/abalone.txt')
all_w_001 = stage_wise(x_arr, y_arr, 0.001, 5000)
print(all_w_001)
all_w_01 = stage_wise(x_arr, y_arr, 0.01, 200)
print(all_w_01)

def stage_wise(x_arr, y_arr, eps=0.01, num_iter=100):
"""
forward stagewise regression算法(前向梯度算法)
是一种近似的 lasso算法
:param x_arr:
:param y_arr:
:param eps:每次特征权重的变化步长
:param num_iter: 迭代次数
:return:
"""
x_mat = np.mat(x_arr)
y_mat = np.mat(y_arr).T
y_mean = np.mean(y_mat, 0)
y_mat = y_mat - y_mean
x_mean = np.mean(x_mat, 0)
x_var = np.var(x_mat, 0)
x_mat = (x_mat - x_mean) / x_var
m, n = np.shape(x_mat)
ws = np.zeros((n, 1))
ws_best = ws.copy()
return_mat = np.zeros((num_iter, n)) # 保存每次迭代最好的权重值
for i in range(num_iter):
# print(ws.T)
lowest_error = np.inf
for j in range(n):
for sign in [-1, 1]:
ws_test = ws.copy()
ws_test[j] += eps * sign
y_test = x_mat * ws_test
rss_err = rss_error(y_mat.A, y_test.A) # 将矩阵转为数组
if rss_err < lowest_error:
lowest_error = rss_err
ws_best = ws_test
ws = ws_best.copy()
return_mat[i, :] = ws.T
return return_mat

逐步回归算法的主要有点在于他可以帮助人们理解现有的模型并作出改进。当构建了一个模型后,可以运行逐步回归算法找出重要的特征,即使停止那些不重要特征的收集。

总结

上面提到的这些线性回归算法,我们应该怎么选择呢?一般来说有一点正则项的表现更好,因此通常你应该避免使用简单的线性回归。岭回归是一个很好的首选项,但是如果你的特征仅有少数是真正有用的,你应该选择Lasso和弹性网络。就像我们讨论的那样,它两能够将无用特征的权重降为零。一般来说,弹性网络的表现要比Lasso好,因为当特征数量比样例的数量大的时候,或者特征之间有很强的相关性时,Lasso可能会表现的不规律。

参考文档

  1. 《吴恩达cs229 课程讲义》
  2. 《机器学习实战》
  3. 机器学习实战_线性回归&逻辑回归(二)

linux鸟哥私房菜收获

发表于 2018-08-30 | 分类于 Linux

最近半个月读完了《linux鸟哥私房菜》这本书,其实在研究生的时候这本书已经读过一遍,这次拿出来读,主要是巩固熟悉一下linux操作系统的相关概念。

这本书整体来说对于初学者还是比较合适的。但是里面也有错误,同时书排版的方式有些地方有些问题,但是这些问题都不是很大。通过阅读这本书,对于linux的了解还是比较深度一些的。如果想要更深入的了解linux,可以看看《Unix & Linux大学教程》这本书,这本书对于命令的介绍和使用会更加深入些。

操作系统

操作系统是硬件和在操作系统上面运行软件的一个中间层。当然这里面包括了很多的内容,包括如何管理硬盘,内存,CPU等等一系列内容。所以一个操作系统要包括以下内容:文件系统,内存管理,网络管理,进程线程管理等等。下面主要聊一聊读了《linux鸟哥私房菜》的一些获得内容。

linux命令

在linux中更常用的还是命令行命令,由于在我们平时的工作中,使用linux主要是作为服务器,而服务器基本上是不提供X Window的。所以掌握linux命令就变得很重要。在linux下面的命令,我们要学会使用帮助文档,即如下获取命令的详细使用说明,其实就是软件程序的使用说明。

命令帮助

1
2
man [command]
[command] --help(-h)

man的输出内容主要包括以下内容:
NAME:简短的命令,数据名称说明
SYNOPSIS:简短的命令执行语法简介
DESCRIPTION:较为完整的说明
OPTIONS:针对SYNOPSIS部分,所有可用的选项说明
COMMANDS:当这个程序在执行的时候,可以在此程序中执行的命令
FILES:这个程序所使用或参考或连接到的某些文件
SEE ALSO:这个命令有相关的其他说明
EXAMPLE:一些可以参考的使用例子
BUGS:是否有错误

命令分类

因为在linux中命令太多了,我们不可能全部都记住的,但是一些常用的还是需要记忆一下的,这样至少我们在使用linux的时候可以能够操作。还有就是我们在使用命令的时候,可以稍微联想一下这个命令对应的英文单词,这样子能够帮助我们进行记忆。比如cd(change directory),mv(move),rm(remove)等等。而且linux下的很多命令在其他的软件中都有相同的意思。比如在docker操作中,docker rm也是代表的删除等意思。其实外国人这些简写都是根据相对应的单词而来。当然我这里仅仅列举了较少的一些命令,更多的命令大家还是多多使用linux进行探索吧。

文件与目录相关管理命令

这部分命令主要是如何新建文件,目录;如何复制,移动文件;如何查看文件,目录等等。常用的命令如下,具体的使用规则可以使用帮助进行查看。

1
2
3
4
cd:切换目录;ls:列出目录和文件;cp:复制;
rm:删除;mv:移动;touch:创建文件;
mkdir:创建文件夹;cat:查看文件内容;more:查看文件内容(每次输出一页);
less:查看文件内容(可以往前翻页)

磁盘和文件系统管理

对于文件系统,大家可以找本关于操作系统原理的书好好了解一下。了解常规的文件系统对于理解分布式文件系统会比较有帮助。文件系统在我们开发的过程中是很重要的,特别是现在容器话,集群化。在linux文件系统中mount(挂载点)的含义,日志系统如何记录文件的操作,inode等等。常用命令如下:

1
2
3
4
df:查看磁盘整体的情况;
du:查看某一个目录的容量情况;
mount:挂载某一个文件系统;
ln:创建连接文件(有点类似于windows的快捷方式,但是分为软连接和硬连接)

文件和文件系统的压缩和打包

在平时我们linux的过程中,tar命令是一个经常出现的命令,掌握tar命令的使用很关键。因为tar命令不光能够打包文件,同时还能够解压文件。

1
2
3
tar:打包文件;
gzip:压缩文件;bzip2:压缩文件;
dump:备份工具

tar命令能够压缩文件是因为这个命令支持gzip和bzip2软件。对于tar命令我们要掌握以下常用的命令
压缩:tar -jcv -f filename.tar.bz2 被压缩的文件或目录名称
查询:tar -jtv -f filename.tar.bz2,可以查看文件内的内容
解压缩:tar -jxv -f filename.tar.bz2 -C 被解压缩的目录

其他常用命令

其他常用的命令,比如管道和数据重定向等等,如果我们需要编写shell脚本,这些命令会非常有用。在linux中掌握shell脚本是很重要的,shell脚本能够帮助我们做一些自动化的事情,代替手工作业。

1
2
grep:匹配文件;sort:排序;
wc:计数,比如统计文件内行数;history:查看历史命令

在linux的学习中,更重要的还是要多用。关记忆这些命令是没有用的,在我们用linux的命令的过程中,仔细想想每个命令的用法,同时加深自己对于这些命令背后的原理以及linux系统本身的原理的理解,相信能够完全掌握linux的使用的

权限理解

因为linux是支持多用户的,即多个人可以同时登陆一台linux系统上的。所以权限管理就变得非常重要。如果不考虑特殊权限的,文件和目录的权限主要分为三种,分别为可读(r)、可写(w)、可执行(x),对应的数字分别为4,2,1。
对于文件,这三个权限比较好理解。那么对于目录呢?
目录可读:你可以查询改目录下的文件名数据,即可以利用ls这个命令将目录下的内容列表显示出来。
目录可写:表示你具有更改该目录结构列表的权限,即在该目录下新建文件和目录;删除已经存在的文件与目录(不论文件的权限如何);将已经存在的文件或目录进行重命名;转移该目录内的文件,目录位置。
目录可执行:目录的x代表用户能否进入该目录成为工作目录的用途。能不能进入某个目录只与该目录的x权限有关。同时如果没有某个目录的x权限,是无法执行该目录下的任何命令。

常用命令

1
chmod:改变文件权限;chown:改变文件所有者;chgrp:改变文件所属用户组

linux常用目录介绍

在linux中,目录的用途是有具体的规范的,即FHS标准。这个规范的目的就是系统让用户可以了解已安装软件通常放置与哪个目录下。大家在平时的使用过程中最好是遵循这些规范。
FHS主要定义了三层目录,分别如下:
/(root,根目录):与开机系统有关
/usr(UNIX software resource):与软件安装/执行有关,可以看到usr是UNIX软件资源的缩写
/var(variable):与系统运作过程有关

根目录分类

根目录一般情况下会有这些目录,目录的含义如下:
/bin:主要放置在单用户维护模式下还能使用的命令,可以被root和一般用户使用,主要由cat,chmod,chown,date,mv,mkdir,cp,bash等
/boot:开机会用到的文件,包括内核文件和开机的配置文件
/dev:因为linux中所有的内容都是文件,而任何设备和接口设备都是以文件的形式存在于这个目录中。
/etc:系统主要的配置文件。例如用户的账户密码,各种服务的起始文件等。
/home:系统默认的用户主文件夹
/lib:开机时会用到的函数库,以及在/bin,/sbin下面的命令会调用的函数库。
/media:可删除的设备,包括软盘,光盘,DVD等
/mnt:如果暂时挂载某些额外的设备,一般建议放置在这个目录中
/opt:给第三方软件放置的目录
/root:系统管理员的主文件夹
/sbin:主要是开机过程中需要的,包括开机、修复、还原系统所需要的命令
/srv(service的缩写):一些网络服务启动之后,这些网络服务需要取用数据的目录。如WWW服务需要的网页数据就可以放置在/srv/www中
/tmp:放置临时文件的目录,重要一般不建议放在这个目录里,因为这个目录会定时清理
/proc:这个目录下的数据都在内存中,如系统的内核,进程,外部设备,网络状态等。

/usr下目录

/usr/bin/:绝大部分的用户可使用命令
/usr/include/:C/C++等程序语言的头文件与包含文件放置处。
/usr/lib/:包含应用软件的函数库、目标文件以及不被一般用户惯用的执行文件或脚本
/usr/local/:系统管理员在本机自行安装自己下载的软件,一般安装在这个目录下
/usr/sbin/:非系统正常运行所需要的系统命令
/usr/share/:放置共享文件的地方
/usr/src/:一般源码放置在这个目录下,而内核源码一般放在/usr/src/linux下

/var 下目录

/var/cache/:应用程序本身运行过程中会产生的一些暂存文件
/var/lib/:程序本身执行的过程中,需要使用到的数据文件放置的目录,比如Mysql数据库放置在/var/lib/mysql,rpm数据库主要放到/var/lib/rpm下
/var/log/:登录文件放置的目录,如/var/log/wtmp(记录登录者的信息)
/var/mail/:放置个人邮箱的目录

你有时候看到的linux系统目录可能不仅仅包括这些或者不存在其中的某些目录,这是因为linux系统版本,同时这也是个规范,有些linux开发厂商会依据这些规范做些修改。所以不一样也没有关系。

总结:因为linux系统包括的内容太多了,这里我仅仅提到了linux系统下的冰山一角。比如如何关机,系统的等级,如何在线安装软件,如何离线安装软件,如何创建用户和用户组,SELinux等等内容。大家都可以通过这本书学到。

<1234>

37 日志
22 分类
45 标签
RSS
© 2024 liang
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4