webdancer's Blog

pages or is-programmer, it is a question

从今年7月份,我将blog由is-programmer平台转到了github的pages平台。转向pages的理由很简单,静态blog很简洁,再加上Scturtle写了一个静态blog生成器。但是用了一段时间以后,我还是决定再转回is-programmer。

什么是Pages?

根据github官方的介绍,github pages就是通过github发布的公共网页,可以自由的通过多种方式来发布网页。github官网对其的介绍:
Github Pages are public webpages freely hosted and easily published through our site. You can publish online using the Automatic Page Generator. If you prefer to work locally you can use the GitHub for Mac and Windows apps, or the command line.
的确Pages很简洁,而且你对你的内容与很大的控制权,不会担心博客内容会丢失。但是同时功能少,如果你想获得一个功能可能很繁琐,这时候会影响你书写内容。当然这很适合那些喜欢折腾的同学,但是我自己觉得这影响了我书写内容。

pages or is-programmer, it is a question

到底选择那个平台,仁者见仁,智者见智。不过,现阶段我还是选择is-programmer吧,这是我的菜。将来,谁知道?不过我的确喜新厌旧,呵呵。

 

机器学习入门

机器学习主要是设计和分析使计算机能够“学习”的算法,这些算法能从经验数据集中发现规律,并根据规律对未知数据做预测。

  1. 那么到底什么是学习呢?我的理解是:广义上来说, 学习就是程序能够根据经验提高自己性能,狭义上来说,从概率图模型的角度,一个完整的建模过程包括:表示,推断,学习,这里的学习就是确定模型中的参数。
  2. 经验数据:那么这些经验数据又从拿来呢?一般来说,可以是人手工整理的数据或是从网络中整理收集的数据。这些数据,或多或少都会混杂着人类的经验。例如:在图像分类的数据集中,可能图片已经由人类手工标注过了。

机器学习已经有了十分广泛的应用,例如:数据挖掘(CV)、计算机视觉(CV)、自然语言处理(NLP)、生物特征识别、搜索引擎(IR)、医学诊断、检测信用卡欺诈、证券市场分析、DNA序列测序、语音和手写识别、战略游戏和机器人运用等。

Tom Mitchell 对机器学习经典的定义[1]:
 A computer program is said to learn from experience E with respect to some class of tasks T and performace measure P, if its performance at tasks T, as measured by P, improves with experience E.
Herbert Simon认为:
Learning is any change in a system that produces a more or less permanent change in its capacity for adapting to its environment.
看以看出,机器学习描述中,涉及到三个基本方面:
  1. 任务T。我们要处理的是一个什么样的任务,是无人汽车设计问题,语言识别,还是人脸识别等等。我们必须对我们要处理的任务有一个清晰的认识。
  2. 性能标准P。我们使用什么样的标准来说明我们模型的好坏,这对我们后面设计学习的目标函数时候有指导作用,我们根据标准P来设计和调整模型,满足我们的任务要求。
  3. 训练经验E。从那里获取训练经验可能对我们系统学习的好坏有非常直接的影响,必须自己选择。
模式识别是通过计算机算法来研究模式的自动处理和判读,也就是从数据中发现规律,并采取相应的动作。模式是指环境和客体,对人类来说,两类很重要的模式是光学和声学信号。现在模式识别的一个常用的手段就是机器学习。在AI领域的两个常见的问题是图像识别和语音识别。举例,一个经典的例子就是“手写字符识别“。我们设计一个learner从一个巨大的手写字符图片库中进行学习,当有新的手写字符图片时,我们希望我们的learner能够做出正确的判断。

两类问题-分类和回归

对于一般的机器学习问题,可以认为去估计一个函数$f:\mathcal{X}\rightarrow \mathcal{Y}$.

两个基本问题是分类和回归问题:
  1. 分类问题输出$\mathcal{Y}$是离散的,例如在二类问题中,输出值通常为:$\{-1,+1\}$;
  2. 回归问题输出$\mathcal{Y}$则是连续的,例如:在曲线拟合问题中,输出为:$\mathbb R$。
分类问题关心的是类别是否匹配,代表每个类别的数字只是一个符号而已,可以换成任意其他符号,并且这些符号之间一般没有什么关系,例如,原本是数字 8 ,把它分类成 7 或者 2 都同样是错误的,并不会因为 7 (从数值上)更接近 8 就是一个更好的结果。在这种情况下,0-1 loss 是最自然的损失函数。而回归问题不一样,比如,今天的气温是 28 度,预测为 25 度很自然地比预测为 2 度要好。说白了就是分类问题中输出是离散的,用了离散度量来衡量相似度,而回归问题中则用了$\mathbb R$上的欧氏度量。对于很多现实问题我们都可以转化为这两类问题。比如:在很多的Email系统中都可以判断一封邮件是否是垃圾邮件,这里涉及到了二类问题。如果我们希望根据以前的二手房成交数据来预测未来的交易价格,则是一个回归问题,我们希望得到的一个具体的价格。

模式识别问题的过程

学习过程中涉及到的名词:feature vector, target vector, data set, training set, test set,performance measure.
  1. feature vector:  $x^i=(x_1,x_2,\dots,x_m);$
  2. target vector: $y^i=(y_1,y_2,\dots.y_k);$
  3. data set:    $X=(x^1,x^2,\dots,x^n); Y=(y^1,y^2,\dots,y^n);$
在上面的表示中,$x^i,y^i$分别表示一个实例的输入和输出;而$x_i$则表示输入的某个特征。m表示输入变量的特征空间;k表示是一个多标签问题,k代表着标签的数目;n则是data set的数目。
  1. 首先,通常是特征提取和选择。特征提取就是将输入的数据转化为特征集合,从而得到特征向量。特征提取就是选择特征的一个子集。特征提取和选择是维度下降(dimension reduction)的主要方法;
  2.  然后,我们就要设计算法,实现一个学习器以满足不同的任务。通常要根据实际应用看是什么问题,从而选择不同的算法类型;
  3. 最后,在不同的数据集上评价我们的模型。

机器学习的不同类型

大多数的机器学习和模式识别识别算法在本质上是基于概率的,使用统计推断的方式给实例加标签。根据算法的不同,我们通常可以做一下的分类[2]:
  1. 监督学习。在监督学习中,训练集合(training set)中的实例是输入值和期望的输出值(通常是人们手工标注的标签或其他值)的二元组。在监督学习中,有训练集合得到一个分类器(分类问题)和回归函数(回归问题),能够对任何的有效输入值做出预测。
  2. 非监督学习。在非监督学习中,训练集合中的实例是由输入值构成的,没有输出值(标注的标签)。在半监督学习中,学习的目标是发现训练数据的结构特征。通常用到的算法有聚类等。
  3. 半监督学习。在半监督学习中,我们使用有标签数据(即上面所说的二元组形式)和无标签的数据一起来构建分类器。
  4. 增强式学习。在增强式学习中,关注在给出的环境中,采取恰当的措施,以取得最大的回报。它最重要的一个特征就是平衡exploration和exploitation的关系,取得一个最优的解。
  5.  其他

评价标准

  1. Accuracy. 指正确分类的数目占总的数目的比例,写成数学公式

\[Accuracy=\frac{right}{total}\]

  1.  Weighted Accuracy. 针对不同类型的错误,加上权值。根据不同的情况赋予不同的值,这样我们就能区别不同的错误。
  2. Precision and Recall。 这个衡量指标常用到文档检索中,查准率(Precision)表示了我们检索出的相关信息占我们检索出信息的比例;而查全率(Recall)则表示了我们检索出的相关信息在整个系统相关文档中的比例。
  3.  F1. 把Precision 和 Recall 这两个指标结合起来的指标是F1 ,定义如下:
  \[F_1= 2 \frac{Precison+Recall}{Precision times Recall}\]
 
  1.  ROC(Receiver Operating Characteristic). ROC是最近很流行的一个评价指标,通过作ROC曲线,计算ROC面积,可以衡量模型作出的预测好坏。
泛化(generation)是指我们的学习器对新的输入的预测能力,如果能很好的处理新输入,则泛化能力好。我们之所以很注重泛化,是因为现实中输入空间是非常大的,我们的训练集只占其中的一小部分。所以在我们考虑实现ML算法的过程中,算法的泛化能力是我们必须考虑的,所以我们要把数据集划分出测试集,在测试集上测试模型的好坏。

实例:多项式曲线拟合

曲线的拟合问题,并不陌生,不管是高中还是大学的课堂中都有接触。在曲线拟合中,我们接触到了一个评价拟合好坏的标准:误差函数(Error Function)。误差函数主要是描述的是训练集中我们的预测值与实际值的差距。常用的误差函数就是平方差的和,如下:
\[
\begin{equation}
\label{least-square-sum}
\mathbb E(w)=\frac{1}{2}\sum_{n=1}^N\{y(x_{n},w)-t_{n}\}^2
\end{equation}
\]
求解的过程一般就是对函数求导,得到关于$w$的线性函数,从而可以得到一个解析解$w^*$。
为了考虑模型的泛化能力,我们需要在测试集上计算$\mathbb E(w)$的值。在这里会出现一个问题:over-fitting。解决这个问题,经常使用的方法就是regularization,公式如下。
\[
\begin{equation}
\label{least-square-sum-with-reg}
 \mathbb E(w)=\frac{1}{2}\sum_{n=1}^N\{y(x_{n},w)-t_{n}\}^2+\frac{\lambda}{2}\|w\|
\end{equation}
\]
正则化的作用就是惩罚系数,可以使参数变得稀疏。
 

机器学习软件

现在有很多的机器学习的软件包,帮助我们快速解决问题,比如:

  • python scikit-learn 
  • shogun toolbox
  • mlpy
  • pylearn2
  • weka
  • R
  • others

当然,我们可能也要实现一些基本的算法,可能会使用具体的矩阵工具和优化工具,比如:

  • matlab/octave
  • numpy,scipy
  • R

在我的笔记中,使用matlab和scikit-learn来演示实现和使用学习算法。

scikit-learn简介

1.数据(Data):在scikit-learn中,有一些自带的数据集,我们通常关注的是数据的特征和目标值。比如数字集合,获取特征和目标值,可以使用下面的代码:

>>> from sklearn import datasets
>>> digits = datasets.load_digits()
>>> digits_data = digits.data
>>> digits_target = digits.target

如果使用‘type’查看一下digits_data和digits_target的类型,可以知道它们是numpy.ndarray类型,这样如果我们自己需要提取特征的时候,只需要保存为这种数据类型,就可以使用scikit-learn 中的方法了。

2.学习和预测:这时机器学习中最核心的部分,使用什么样的模型,确定了这种模型后,如何更快更准确的进行学习,如何改进模型,提高泛化的能力。在scikit-learn 中,进行分类(或是其他任物)的估算器(estimator)是实现了fit(X,Y)和predict(X)的python对象。

>>> from sklearn import svm
>>> clf = svm.SVC(gamma=1e-4,C=100)
>>> clf.fit(digits_data[:-1],digits_target[:-1])
SVC(C=100, cache_size=200, class_weight=None, coef0=0.0, degree=3,
  gamma=0.0001, kernel='rbf', max_iter=-1, probability=False,
  random_state=None, shrinking=True, tol=0.001, verbose=False)
>>> clf.predict(digits_data[-1],digits_target[-1])

如果想要保存我们训练的模型,可以使用python库中的pickle模块。

>>> import pickle
>>> model = pickle.dumps(clf)
>>> clf2 = pickle.loads(model)

引用

1.机器学习,<http://www.cs.cmu.edu/~tom/mlbook.html>
 
2.http://en.wikipedia.org/wiki/Machine_learning

理解过程抽象

在学习编程的过程中,一个核心的任务是编写可以完成我们任务的函数。不管我们使用的什么语言,做什么开发,函数抽象并不少见。所谓的函数,我认为就是一些语句的集合,完成一个特定的任务。有了函数,我们思维时的操作原子型的层次变的比较高,思维的难度就会降低。但是在不同的编程实践中,为了完成任务需要的编写函数的思维方式也许是不同的,这会受到编程语言或是第三方库的影响。

在面向对象编程中,想得是如何构建类以及如何设计类之间的关系,充分利用对象的特性,例如在使用Java编程中,会想着如何设计Class,使用什么样的设计模式,这时候函数抽象的层次依赖与我们的类设计。在使用C这样的编程语言时,使用面向对象的设计,还是直接使用函数用来模块化,也会带来不同的设计函数的思维方式。使用像Lisp这样的函数式编程语言时,我们的思维与过程式的编程语言的方式可能会有很大的不同,函数就处于核心地位了。编程的思维可能会受到我们学习过的很多东西的影响,正如上面我陈述的。我的经验是学会抽象和使用语言提供的高层抽象,这样会大大的减低我们抽象函数的难度,使我们的注意力集中到解决我们的问题。通过自己的抽象和语言提供的高层抽象来实现层次化。
 
下面我使用不同的编程语言实现了冒泡排序,体会一下编程语言对我们思维的影响。
对冒泡排序,我还是比较熟悉的。算法的基本思想就是:两个指针i,j,i控制每次冒泡一遍的bubble的位置,j控制每一边冒泡时要比较的数的位置,两次循环就行了。
 
C语言实现
#include<stdio.h>

    void swap_int(int * a, int * b){
        int tmp=0;
        tmp=*a;
        *a=*b;
        *b=tmp;
    }

    void bubblesort(int * a,int n){
        int i;
        int j;
        for(i=0;i<n-1;i++){
            for(j=n-1;j>i;j--){
                if (a[j]<a[j-1]){
                    swap_int(&a[j],&a[j-1]);
                }
            }
        }
    }
在写这段代码时,我饭的错误就是给`swap_int`传递实参的时候没有取地址,这就是我对`C`语言的思维的盲区,对于`a[j]`与`a+j`我没有他们不同的认识。
 
python实现
    def bubblesort(l):
        n=len(l)
        for i in range(n-1):
            for j in range(n-1,i,-1):
                if l[j]<l[j-1]:
                    l[j],l[j-1]=l[j-1],l[j]
显然`python`要比C短的多,但这不代表我没有出错,因为有一段时间没写代码了,所以对`range(a,b)`的区间表示方式到底用了`[a,b]`还是`[a,b)`已经有点模糊不清了,所以就出了错。当然这种基本的问题,我们应该很明确的,但是尽管如此,我还是出错了。
 
java实现
    public class BubbleSort{

        public static void sort(int[] l){
            int n=l.length;
            for(int i=0;i<n;i++){
                for(int j=n-1;j>i;j--){
                    if(l[j]<l[j-1]){
                        swap_int(l,j,j-1);
                    }
                }
            }
        }

        private static void swap_int(int[] l,int m,int n){
            int tmp=l[m];
            l[m]=l[n];
            l[n]=tmp;
        }
    }
尽管`java`代码已经很久没写了,但是`java`与`c`的过程太相似了,基本没有费功夫,这里就是感觉java只有传值的参数传递方式的原因,`swap`函数一点也不优雅。
 
scheme实现
    (define (bubblesort l)
     (let ((n (vector-length l)))
     (map (lambda (i)
           (map (lambda (j) 
                 (if (< (vector-ref l j) (vector-ref l (- j 1)))
                  (swap l j (- j 1))))
            (range (- n 1) i -1)))
           (range 0 n 1))))

    (define (swap l a b)
     (let ((tmp (vector-ref l a)))
      (vector-set! l a (vector-ref l b))
      (vector-set! l b tmp)))

    (define (range low high step)
     (if (or (and (> step 0) (> low (- high 1))) (and (< step 0) (< low (+ high 1))))
      ()
      (cons low (range (+ low step) high step))))

    (define l (vector 2 3 1 5 4 7 8 9 1))
    (bubblesort l)
    (display l)
写`scheme`代码,因为最近在看`SICP`,所以代码的错误只是笔误,变量名写错这样的原因,可是我还是没能使用函数式的编程方式来写这段代码,主要就是函数式编程就要使用辅助的空间,所以使用了赋值操作。
 
从上面的过程中我有这么几个总结:
  1. 过程抽象对于我们解决问题,非常有用。使用高级语言提供的机制,可以大大解放我们的编程效率。
  2. 理解问题的时候,通常没法子一下理解的很好,所以在对问题的理解上,要多花功夫。
  3. 在写过程式的语言时,对于一些地方很模糊,这就是我们训练的地方。
  4. 函数式的编程方式,对思维的训练量很大。
思维是一个逐渐完善的过程,我们不能期望它一下子满足期待,要循序渐进的推进。要不断的训练,并且反馈,也许我们才会有一个比较好的抽象函数的能力,不管是面向对象编程还是函数式编程。

 

生成毕业论文清单的python脚本

快乐的大学生活就要结束了,到了毕业季,大家在兴奋中有充满了伤感,不知道何时才能再度重逢,再像这样一起生活四年是不可能了。我们应该珍惜自己身边的朋友,也许有各种毛病,但是,是人就有毛病,没有的话,那就成神了。

闲话不说了,今天早上整理同学的论文,可能是自己没做好通知,大多数同学的文件名都有问题,非常蛋疼的一个一个的帮同学修改文件名。然后去教务处交上了,但是忘了做论文的清单了,难道又要一个一个的输吗?想了想,用python写个脚本吧。因为我已经手动的帮把文件名都改成了:学号_姓名的格式,刚开始的思路,只是将文件名和学号处理一下,让程序自动的把这学号和姓名写入xls文件;但是还有论文题目,指导老师,这两项还是要一个一个的输,看了看论文,尽管有的同学的首页有问题,但是大多数同学的首页都包含了这四种信息,那就不如直接处理word文件了,把信息提取出来,直接写入xls文件。

程序的思路:

  1. 使用win32com把word转为txt文件;
  2. 读取txt文件,在前30行中搜索姓名,学号,题目,导师信息;
  3. 把提取的信息写入xls文件。

思路比较简单,程序写了一下午,主要是对win32com不熟悉,还有让人窒息的汉字编码问题,耗费了大多数时间。跑了一下,程序的效果还是比较好的,只有几个同学的文档没有按照学校给的模版写,没有抓到信息,其他的都搜到了。

 

# -*- coding: utf-8 -*-
import fnmatch, os, sys, win32com.client  
from tempfile import TemporaryFile
from xlwt import Workbook
# prepare xls file
book = Workbook(encoding='utf-8')
sheet1 = book.add_sheet('Sheet 1')
sheet1.write(0,0,'学号')
sheet1.write(0,1,'姓名')
sheet1.write(0,2,'论文题目')
sheet1.write(0,3,'专业')
sheet1.write(0,4,'指导老师')
sheet1.col(0).width = 5000
sheet1.col(1).width = 5000
sheet1.col(2).width = 10000
sheet1.col(3).width = 5000
sheet1.col(4).width = 5000

# retrive informatio from doc
index=1
wordapp = win32com.client.gencache.EnsureDispatch("Word.Application")  
try:  
      for path, dirs, files in os.walk(sys.argv[1]):  
            for filename in files:  
                  if fnmatch.fnmatch(filename, '*.doc'):
                      filetype=1
                  elif fnmatch.fnmatch(filename, '*.docx'): 
                      filetype=2
                  else:
                      continue
                  doc = os.path.abspath(os.path.join(path, filename))  
                  print "processing %s" % doc  
                  wordapp.Documents.Open(doc)  
                  if filetype==1:
                      docastxt = doc[:-3] + 'txt'  
                  else:
                      docastxt =doc[:-4]+'txt'
                  wordapp.ActiveDocument.SaveAs(docastxt,FileFormat=win32com.client.constants.wdFormatText)  
                  wordapp.ActiveDocument.Close( )  
                  f=open(docastxt,'r')
                  namefound=False
                  numberfound=False
                  titlefound=False
                  adfound=False
                  i=0
                  metadata=[u'prob']*5
                  for line in f:
                      line=unicode(line,'gbk')
                      i=i+1
                      if i>30:
                          break
                      if namefound and numberfound and adfound:
                          break
                      if titlefound:
                          metadata[2]=line.lstrip().rstrip()
                          titlefound=False
                          pass
                      if line.find(u'号')!=-1:
                          metadata[0]=line.split()[-1]
                          namefound=True
                      elif line.find(u'姓')!=-1:
                          metadata[1]=line.split()[-1]
                          numberfound=True
                      elif line.find(u'题目')!=-1:
                          titlefound=True
                      elif line.find(u'师')!=-1:
                          metadata[4]=line.split()[-1]
                          adfound=True
                  metadata[3]=u'计算机科学与技术'        
                  print 'number: %s, name: %s, title: %s,dap: %s, ad: %s'%(metadata[0],metadata[1],metadata[2],metadata[3],metadata[4])
                  for meta in range(5):
                      print index,meta
                      sheet1.write(index,meta,metadata[meta])
                  index+=1
                  f.close()
                  os.remove(docastxt)

      book.save('08_1_auto.xls')
      book.save(TemporaryFile())

finally:  
      # 确保即使有异常发生Word仍能被正常关闭  
      wordapp.Quit( ) 

计算PageRank

在上一篇文章中,介绍了PageRank算法的基本原理,这里讨论一下如何计算PageRank的值。我们还是使用上一篇使用的例子,系统结构图如下:

由PageRank的原理可以知道,一个页面的PageRank值主要是由系统的图结构(M)和阻尼因子(d)决定的。根据经验d的取值为0.85。

PageRank可以用Markov Chain的理论来解释,我们可以根据图的邻接矩阵$A$计算一个随机矩阵$M$。

由邻接矩阵得到随机矩阵具体的过程:

  1. 如果一行中没有1,全为0,则用$\frac{1}{N}$来代替0,其他的行如下处理;
  2. 每个1都除以这行中1的个数,即:$\frac{A_{i,j}}{\sum_j{A_{i,j}}}$;
  3. 用$d$乘以上面得到的矩阵;
  4. 在上面得到的矩阵的每个元素加上$\frac{1-d}{N}$,从而得到$M$;

上图的邻接矩阵可以表示为:

根据上面给出的算法,可以得到随机矩阵:

在随机矩阵中,stationary probability vector$\pi$是在随机矩阵的作用下值不变。其定义如下:

$\pi P = \pi$。 

根据Perron–Frobenius theorem定理,随机矩阵总会存在一个stationary probability vector,而这个特征向量正好就是我们要求的PageRank。有很多的方法可以求解,最常用的是:power method.

算法描述如下:

  1. 初始化向量$x_0$;
  2. 计算$x_{(t+1)}=x_tM$;
  3. 判断是否$|x_{(t+1)}-x_t| < \epsilon$,如果是,停止;否则,跳到2.

参考:

1.http://en.wikipedia.org/wiki/PageRank

2.http://nlp.stanford.edu/IR-book/html/htmledition/the-pagerank-computation-1.html#pagerank

 

ps: 不知道为什么不能显示矩阵,只能转为图片了。

 

 

PageRank简介

今天去听了一个讲座,讲的是基于机器学习方法的rank算法,讲到了PageRank(google.com)和HITS(ask.com)算法,本来就像看看PageRank是怎么回事,刚好借此机会学习一下。

 
概念
 
PageRank是以google创始人Larry Page命名的一种链接分析算法,它根据网页的相关性和重要性来给网页赋予一个权重值。一个网页p的权重值通常被p的PageRank,记作: PageRank(p)。
 
原理
 
一个页面的“得票数”由所有链向它的页面的重要性来决定,到一个页面的超链接相当于对该页投票。一个页面的PageRank是由所有链向它的页面(“链入页面”)的重要性经过递归算法得到的。一个有较多链入的页面会有较高的等级,相反如果一个页面没有任何链入页面,那么它没有等级。简言之,“被越多优质的网页所指的网页,它是优质的概率就越大”。
 
看下面一个简单的例子,我们假设我们要处理的系统中含有四个页面(当然,实际的www有的页面数目要远远的大于这个数目),如下图所示。其中A,B,C,D四个节点代表了四个页面,其中B链接到了A,C,C链接到了A,D链接到了A,B,C。
 

 

现在我们来考虑一下PageRank的意思,假定我们有一个随机浏览者(random surfer),他在网上随机的浏览网页,现在他处于页面D,他有相同的概率去访问D链接到的页面,即概率为:$frac{1}{3}$,当他在页面上这样随机访问的时候,一些网页会比另外一些网页更经常的访问到。直觉上看,那些有更多链接指向他的页面要更容易被访问到。这也就是PageRank背后的思想:更经常访问的网站更重要。
 
下面计算A点的PageRank值。我们假设一个页面不能投票2次,所以B给每个页面半票,以同样的逻辑,D投出的票只有三分之一算到A的PageRank上。那么:
 
$PR(A) = \frac{PR(B)}{2} + PR(C) + \frac{PR(D)}{3}$
 
设L(p)为从页面p链接到的页面数目,则上面的式子可以写为:
 
$PR(A) = \frac{PR(B)}{L(B)} + \frac{PR(C)}{L(C)} + \frac{PR(D)}{L(D)}$
 
我们可以得到一般情况下,任意页面p的PageRank式子:
 
$PR(p_i) = \sum_{p_j \in M(p_i)} \frac{PR(p_j)}{L(p_j)}$
 
一个页面不能投票两次比较很理解,例如在上面的例子中,如果B,C页面的PR值不平均开,那么A链接的PR值肯定会超过B,C,如果A是一个新网站,而B,C都是经典网站,显然这种情况就有问题,而且平均开更符合我们的直觉:如果从B页面上随机的点击的话,那么B页面上每个链接的概率都是一样的,它的PR值也应该是平均开的。
 
对于那些没有链出的页面,比如例子中的A节点,没有链出,我们引入阻尼系数d(damping factor )的概念后,原来可能被分割的网络就变得连通起来,今天听那个老师讲这样最后的PageRank值最后就会收敛,从而用来进行排序。这样计算的公式变为:
 
$PR(p_i) = \frac{d}{N}+ d (\sum_{p_j \in M(p_i)} \frac{PR(p_j)}{L(p_j)})$
 
其中,N为链接到$p_i$的总的页面数目。
 
计算
常用的两种方法就是:数值迭代和线性代数的方法。后面在好好分析一下吧!

 

ubuntu下安装与使用vim-latex suite

 
1、下载插件
从http://sourceforge.net/projects/vim-latex/files/下载vim-latex插件。
2、安装插件
  1. 解压下载的压缩包到~/.vim目录。
  2. 设置vimrc。详细参见:http://vim-latex.sourceforge.net/documentation/latex-suite/recommended-settings.html
  3. 安装help文件。helptags ~/.vim/doc
  4. 设置Vim-latex-suite。使用xelatex命令进行文档的编译,利用evince浏览生成的pdf文档。可以通过修改~/.vim/ftplugin/latex-suite/texrc完成这些操作。
#第88到92行,我进行了如下修改,就是让tex总是被编译成pdf

88 if has('macunix')

89 TexLet g:Tex_DefaultTargetFormat = 'pdf'

90 else

91 TexLet g:Tex_DefaultTargetFormat = 'pdf'

92 endif


#第117行修改,使用xelatex完成 tex -> pdf 的编译

114 " ways to generate pdf files. there are soo many...

115 " NOTE: pdflatex generates the same output as latex. therefore quickfix is

116 "       possible.

117 TexLet g:Tex_CompileRule_pdf = 'xelatex -interaction=nonstopmode $*'



修改147行,指定用evince程序打开pdf文档

144 elseif has('macunix')

145 " Let the system pick.  If you want, you can override the choice here.

146 TexLet g:Tex_ViewRule_ps = ''

147 TexLet g:Tex_ViewRule_pdf = 'evince
 
        5.重启vim。
 
 
==================================转========================================
1. 初用时需熟记的几个键:Ctrl-J,F5, F7,F9,Shift-F5,Shift-F7,\ll (compile快捷键),\lv(view pdf 快捷键),\ls,Ctrl-X Ctrl-K(根据字典补全) 等。
 
2.  写出\cite{ 后按 F9 无反应,没有给出交叉引用,原因在于vim中的Python接口对latex-suite来说有些问题,将其禁用即可。只需要将 ~/.vim/ftplugin/latex-suite/texrc 中默认的打开~/.vim/ftplugin/latex-suite/texrc,将
TexLet g:Tex_UsePython = 1
                         改为
TexLet g:Tex_UsePython = 0
                      就行了!
 
3. 为了能够正向搜索,应设定好参数并使用\ll编译,然而当工作目录下有makefile时,\ll并非执行设定的编译命令,而是执行makefile,于 是导致无法正向搜索,郁闷了半天。其实只要禁用makefile即可,同样~/.vim/ftplugin/latex-suite/texrc中
TexLet g:Tex_UseMakefile = 0
 
4. 正向搜索设置,在 ~/.vim/ftplugin/tex.vim 中指定
let g:Tex_CompileRule_dvi='latex -src-specials -interaction=nonstopmode $*'
说明上说还要设定  :TCTarget dvi ,可是没有设也行,反而把这句话写在上面文件中时运行vi会提示错误,但是在vi中执行该命令却可以,反正能用就不管它了。设定好了以后需重新编译tex文件(用\ll),然后\ls可以搜索并预览。
 
5. 反向搜索,参考了 http://bbs.ctex.org/viewthread.php?tid=39072&extra=&page=1
注意反向搜索仅支持gvim,且gvim要以远程模式启动:
gvim --servername latex-suite --remote-silent   filename.tex
启动后  为了能够使用反向搜索,必须让 xdvi 知道当前编辑器是工作在 remote 模式下的
VIM,以便在用户搜索的时候调用编辑器显示查找结果。在你的 ~/.vimrc 或~/.vim/ftplugin/tex.vim中添加以下内容:
let g:Tex_ViewRule_dvi="xdvi -editor 'gvim --servername latex-suite --remote-silent'"
这样便可\ll编译后\ls查看了,反向搜索时记住要按着Ctrl键双击某处 (似乎左键单击即可),就会跳到tex源文件的相应地方。
 
6.  为了方便,自己也做了一些设置,包括快捷键,在 ~/.vim/ftplugin/tex.vim 中:
map    <F4>   <ESC>:q<CR>      "F4关闭窗口(buffer)
map    <F2>   <ESC>:w<CR>\ll   "F2保存并编译
imap   <F2>   <ESC>:w<CR>\ll
map    <F3>   <ESC>\lv                  "F3查看
imap   <F3>   <ESC>\lv
nmap   <Tab>  <C-j>                    "用Tab键来代替Ctrl-j跳转,方便多了
imap   <Tab>  <C-j>
vmap   <Tab>  <C-j>
set keywordprg=:help         "按K键查找光标处单词的帮助,默认是man
cmap  xxx   !make                
set    iskeyword+=.,_       "便于fig.xx,prl101_12345等形式的搜索补全,否则默认情况下不把fig.xx当成一个词,而是当成fig和xx两个次,中间的“.”被当做词的分隔符了。
 
7. 其实只要  latex -src-specials -interaction=nonstopmode  xxx.tex
编译出的dvi文件,就已经包含了正向与反向搜索的信息,就可以正向或反向搜索,如果是用xdvi打开的话,按Ctrl左键单击便可反向搜索,只不过xdvi默认弹出的是 xterm -e vi 的窗口,其实是可以自己指定编辑器的,比如 
xdvi -editor gedit 
照样反向搜索,至于上面所加的gvim的参数只是保证不是每次反向搜索都要打开一个gvim窗口而已。
 
8. 临时取消快捷键定义,比如你想输入双引号,可是一打出"就自动变成``,那么要怎么禁止自动替换,直接输出"呢?
记住 <Ctrl-v> 即可!
<Ctrl-v>" 得到 "
SS<Ctrl-v>S 得到 SSS
~<Ctrl-v>~ 得到 ~~
 

系统迁移

话说在我的t60上跑win7还是有点吃力,感觉最近用的软件好像linux下几乎都有,干脆直接割掉win,转到linux单系统。反正实验有win7,如果需要就远程登录吧。

前期准备:

关注的问题主要有三个:数据;应用程序;linux发行版的选择
 
1.数据
怎么把自己的数据能够进行有效的迁移,进行的方式是云端+本地数据结合。迁移的主要数据类别为:
    >>书籍。自己保存的电子书,使用坚果铺子同步。
    >>文档。自己写的一些文档,使用坚果铺子同步。
    >>代码。自己写的代码和整理的代码库,使用git管理,github做代码仓库。
    >>音乐。自己下载的一些音乐,数量不是很大,主要是收藏音乐列表同步,使用坚果铺子。
    >>视频。不用转移,看过就删了。
    >>软件配置。
        >>vim的插件和vimrc。
        >>网络配置。ip,hosts等
 
2.程序
看看windows下面使用的程序在替代程序(软件顺序是按windows软件管理的排序)。
    >>utorrent -->> wine utorrent / utorrent server
    >>vim -->> vim
    >>ms office -->> libre office(兼容性问题,暂时没有好办法)
    >>adobe flash player -->> adobe flash player
    >>CAJViewer -->> 没有很好的替代软件,不过用处不大
    >>Ctex -->> texlive
    >>evernote -->> web evernote
    >>foxmail -->> thundbird
    >>git -->> git
    >>gnuplot -->>gnuplot
    >>chrome -->> chrome
    >>sun JDK -->> openJDK
    >>matlab -->>matlab
    >>VC -->> gcc
    >>firefox -->>firefox
    >>PDF-Viewer -->> 文档查看器
    >>PPTV -->> web pptv
    >>python -->> python
    >>R -->> R
    >>ting -->> web ting /weibo music
    >>xchat -->> xchat
    >>阿里旺旺 -->> web(这个也是不好办)
    >>坚果云 -->> 坚果云
    >>搜狗输入法 -->> ibus 拼音
    >>QQ -->> web QQ
    >>有道词典 -->> web 有道,星际霸王
    >>goagent-->> goagent
 
3.linux发行版和软件源
 
linux的发行版很多,这应该是你迁移到linux的动力,而不是阻碍。
我选择ubuntu 12.04,使用中科大的源。
 
转移遇到的问题
  1. 网络设置。不知道unbutu里面的network-manager-gnome怎么又抽风了,反正没能设置成功,删了。那只能手动设置interfaces和resolv.conf,气人的是ubuntu的dns设置更改了,那只能通过resolvconf工具来改了。
  2. vim。由于我的vim插件是直接从win拷过来的,很多插件提示,多余的M结尾符,通过set ff=unix解决。
  3. tex。在win下面,使用的是ctex,由于对中文支持较好,转到ubuntu下面,使用texlive,集成了xetex,加上vimlatex感觉够用了。
  4. 看球。由于以前在win下用pplive看球,现在只能上pptv.com上看了,不过有些节目不能直播,比较悲剧。不知道为什么不能看北邮的iptv,这点悲剧了。。。。

 




Host by is-Programmer.com | Power by Chito 1.3.3 beta | © 2007 LinuxGem | Design by Matthew "Agent Spork" McGee