Matlab正则表达式 | Matlab 正则表达式语法

处理数据过程中,需要用到这个正则表达式,摘抄了点资料,贴到自己空间里了,本文系转载。略有修改。

正则表达式是一个重要的编程概念(各种语言都有,正则是一个很强大的东东)。应用正则表达式可以实现很多强大的字符处理功能,有时也可以为常规方法解决起来比较复杂的问题另辟蹊径。

1. 引言

正则表达式就是一个表达式(也是一串字符),它定义了某种字符串模式——利用正则表达式,可以对大段的文字进行复杂的查找、替换等。这里以 Matlab 为编程语言,结合实例讲解正则表达式的概念和使用方法。

Matlab 提供的正则表达式函数有三个:

regexp——用于对字符串进行查找,大小写敏感;

regexpi——用于对字符串进行查找,大小写不敏感;

regexprep——用于对字符串进行查找并替换。

简要介绍一下这三个函数,以 regexpi 为例:

用法 1:

[start end extents match tokens names] = regexpi(‘str’, ‘expr’)

start 为匹配字符串的起始位置;end 为匹配字符串的终止位置;extents 为扩展内容,和’tokens’指示符一起用,指示出现 tokens 的位置;match 即找到的匹配字串;tokens 匹配正则表达式中标记(tokens)的字串;names 为匹配到的命名标记的标记名。

用法 2:

若不需要所有的输出,可以用下面的方式有选择的输出。

[v1 v2 …] = regexpi(‘str’, ‘expr’, ‘q1’, ‘q2’, …)

‘q1’、’q2’ …… 为 ‘start’、’end’、’tokens’、’tokensExtents’、’match’、’names’ 之一,意义与前文相同。v1、v2…… 的输出顺序与 q1、q2…… 一致。

2. 单个字符的匹配

我们先从简单的开始 —— 以 regexpi 函数为例,不区分字符的大小写。假设你要搜索 ‘cat’,搜索用的正则表达式就是 ‘cat’,这与文本编辑工具里常用的 CTRL+F 是一样的,即正则表达式 ‘cat’ 匹配 ‘cat’、’Cat’、’cAt’、’CAt’、’caT’、’CaT’、’cAT’、’CAT’。

为了方便,下面的叙述中字符串和正则表达式的”都省略不写。

2.1 句点符号

.— 匹配任意一个(只有一个)字符(包括空格)。

你在玩英文拼字游戏,想要找出三个字母的单词,而且这些单词必须以 ‘t’ 字母开头,以 ‘n’ 字母结束;另外,有一本英文字典,你可以用正则表达式搜索它的全部内容。要构造出这个正则表达式,你可以使用一个通配符——句点符号’.’ 。这样,完整的表达式就是 t.n,它匹配 tan、ten、tin 和 ton,还匹配 t#n、tpn 甚至 t n,还有其他许多无意义的组合。这是因为句点符号匹配所有字符,包括空格,即:正则表达式 t.n 匹配 ten、tin、ton、t n、tpn、t#n、t@n 等。

Matlab 程序实例:

clear;clc

str=’ten,&8yn2tin6ui>&ton, t n,-356tpn,$$$$t#n,4@).,t@nT&nY’;

pat=’t.n’;

o1=regexpi(str,pat,’start’) %用’start’指定输出 o1 为匹配正则表达式的子串的起始位置

o2=regexpi(str,pat,’end’) %用’end’指定输出 o2 为匹配正则表达式的子串的结束位置

o3=regexpi(str,pat,’match’) %用’match’指定输出 o3 为匹配正则表达式的子串

[o11,o22,o33]=regexpi(str,pat,’start’,’end’,’match’) %同时输出起始位置和字串

输出为:

o22 = 3 8 13 18 23 28 33 36

o33 = ‘ten’ ‘tin’ ‘ton’ ‘t n’ ‘tpn’ ‘t#n’ ‘t@n’ ‘T&n’

o1 = 1 10 18 23 31 39 48 51

o2 = 3 12 20 25 33 41 50 53

o3 = ‘ten’ ‘tin’ ‘ton’ ‘t n’ ‘tpn’ ‘t#n’ ‘t@n’ ‘T&n’

o11 = 1 10 18 23 31 39 48 51

o22 = 3 12 20 25 33 41 50 53

o33 = ‘ten’ ‘tin’ ‘ton’ ‘t n’ ‘tpn’ ‘t#n’ ‘t@n’ ‘T&n’

2.2 方括号符号

[oum]——匹配方括号中的任意一个。

为了解决句点符号匹配范围过于广泛这一问题,你可以在方括号([])里面指定看来有意义的字符。此时,只有方括号里面指定的字符才参与匹配。也就是说,正则表达式 t[aeio]n 只匹配 tan、Ten、tin 和 toN等。但 Tmn、taen 不匹配,因为在方括号之内你只能匹配单个字符。

Matlab 程序实例:

clear;clc

str=’ten,&8yn2tin6ui>&ton, t n,-356tpn,$$$$t#n,4@).,t@nT&nY’;

pat=’t[aeiou]n’;

[o11,o22,o33]=regexpi(str,pat,’start’,’end’,’match’) %í?ê±ê?3??eê?????oí×ó′?

o11 = 1 10 18

o22 = 3 12 20

o33 = ‘ten’ ‘tin’ ‘ton’

2.3 方括号中的连接符

‘[c1-c2]’ —— 匹配从字符 c1 开始到字符 c2 结束的字母序列(按字母表中的顺序)中的任意一个。 例如 [a-c] 匹配 a、b、c、A、B、C,即正则表达式 t[a-z]n 匹配 tan、tbn、tcn、tdn、ten、……、txn、tyn、tzn。

Matlab 程序实例:

clear;clc

str=’ten,&8yn2tin6ui>&ton, t n,-356tpn,$$$$t#n,4@).,t@nT&nY’;

pat=’t[a-z]n’;

[o11,o22,o33]=regexpi(str,pat,’start’,’end’,’match’)

o11 = 1 10 18 31

o22 = 3 12 20 33

o33 = ‘ten’ ‘tin’ ‘ton’ ‘tpn’

2.4 特殊字符

\.等 —— 即由 ‘\’引导的,代表有特殊意义或不能直接输入的单个字符。

在使用 fprintf 函数输出时我们常用’\n’来代替回车符,这里也是同样的道理,用\n在正则表达式中表示回车符。类似的还有\t横向制表符,’\*’表示’*’等。后一种情况用在查询在正则表达式中有语法作用的字符,详见下文。

下面是一些匹配单个字符的转义字符正则表达式及所匹配的值。

\xN 或\x{N} 匹配八进制数值为 N 的字符

\oN 或\o{N} 匹配十六进制数值为 N 的字符

\a Alarm(beep)

\b Backspace

\t 水平 Tab

\n New line

\v 垂直 Tab

\f 换页符

\r 回车符

\e Escape

\c 某些在正则表达式中有语法功能或特殊意义的字符 c,要用 \c 来匹配,而不能直接用 c 匹配,例如 . 用正则表达式 \. 匹配,而 \ 用正则表达式 \\ 匹配。

Matlab 程序实例:

clear;clc

str=’l.[a-c]i.$.a’;

pat1=’.’;pat2=’\.’;

o=regexpi(str,pat1,’match’)

o1=regexpi(str,pat2,’match’)

输出为:

o = ‘l’ ‘.’ ‘[‘ ‘a’ ‘-‘ ‘c’ ‘]’ ‘i’ ‘.’ ‘$’ ‘.’ ‘a’

o1 = ‘.’ ‘.’ ‘.’

2.5 类表达式

\w、\s和\d 等——匹配某一类字符中的一个。

和上面的 \n 等表中的转义字符有所不同,\w、\s、\d 等匹配的不是某个特定的字符,而是某一类字符。具体说明如下:

\w 匹配任意的单个文字字符,相当于 [a-zA-Z0-9_];

\s 匹配任意的单个空白字符,相当于 [\t\f\n\r];

\d 匹配任意单个数字,相当于 [0-9];

\S 匹配除空白符以外的任意单个字符,相当于 [^\t\f\n\r] —— 方括号中的^表示取反;

\W 匹配任意单个字符,相当于 [^a-zA-Z0-9_];

\D 匹配除数字字符外的任意单个字符,相当于 [^0-9]。

Matlab 程序实例:

s=’This city has a population of more than 1,000,000.’;

ptn=’\d’;

regexp(s,ptn,’match’)

输出为:

ans = ‘1’ ‘0’ ‘0’ ‘0’ ‘0’ ‘0’ ‘0’

3.字符串的匹配

3.1 多次匹配

例如需要匹配 ‘ppp’,那么就可以用正则表达式’ppp’,还有一种更简单一点的记法 ‘p{3}’。正则表达式中的'{}’用来表示匹配前面的表达式的出现次数,即’p{2,3}’匹配’pp’和’ppp’。除了'{}’,还有几个字符,用在表示单个字符的正则表达式后面表示次数,如下所述:

expr? 与 expr 匹配的元素出现 0 或 1 次,相当于{0,1}

expr* 与 expr 匹配的元素出现 0 次或更多,相当于{0,}

expr+ 与 expr 匹配的元素出现 1 次或更多,相当于{1,}

expr{n} 与 expr 匹配的元素出现 n 次,相当于{n,n}

expr{n,} 与 expr 匹配的元素至少出现 n 次

expr{n,m} 与 expr 匹配的元素出现 n 次但不多于 m 次

假设我们要在文本文件中搜索美国的社会安全号码。这个号码的格式是 999-99-9999。用来匹配它的正则表达式为 [0-9]{3}\-[0-9]{2}\-[0-9]{4}。在正则表达式中,连字符(“-”)有着特殊的意义,因此,它的前面要加上一个转义字符\。

如果希望连字符号可以出现,也可以不出现 —— 即 999-99-9999 和 999999999 都属于正确的格式。这时,你可以在连字符号后面加上 ‘?’ 数量限定符。这样正则表达式为 [0-9]{3}\-?[0-9]{2}\-?[0-9]{4}。 另外,当我们使用 expr* 时,Matlab 将尽可能的匹配最长的字符子串。如:

>>str = ‘

xyz’;

>>regexp(hstr, ”, ‘match’)

ans = ‘

如果我们希望匹配尽可能短的字符子串时,可以在上面我们使用的字符串后使用 ‘?’,也就是 expr*?,

例如:

>>str = ‘

xyz’;

>>regexp(hstr, ”, ‘match’)

ans = ‘

‘ ‘

‘ ‘‘ ”

这个表达式的执行过程是这样的,先执行 expr*,“游标”(如果有的话)就指到了与 expr* 匹配的字符子串的最末端,然后从那里开始再检查下一个字符与后面的表达式是否匹配,如果匹配就继续向前(如果一直成功则返回最长的字符串),如果不匹配则直接返回空。例如:

>>str = ‘

xyz’;

>>regexp(hstr, ”, ‘match’)

ans = {}

>>regexp(hstr, ‘

ans = ‘

xyz’

3.2 逻辑运算符

exp|exp2 表示或者满足 exp 或者满足 exp2。

(expr) 将 expr 标记为一组,匹配 expr,并将匹配的字符子串标记起来以供后面使用。关于这部分内容下面还会有更详细介绍。

(?:expr) 表示 expr 为一组,相当于数学表达式中的()

例如:

lstr=’A body or collection of such stories’;

regexp(lstr,'(?:[^aeiou][aeiou]){2,}’,’match’)

ans = ‘tori’

上面的表达式中 {2,} 对 [^aeiou][aeiou] 起作用,如果去掉分组,则只对 [aeiou] 起作用,如下所示:

>>regexp(lstr,'[^aeiou][aeiou]{2,}’,’match’)

ans = ‘tio’ ‘rie’

(?>expr) expr 中的每个元素是一个分组。(?#expr) 放在(?#和)之间的是注释。如:

>>regexp(lstr, ‘(?# Match words in caps)[A-Z]\w*’, ‘match’)

ans = ‘A’

expr1|expr2 匹配 expr1 或者 expr2 两者之一即可。

>>regexp(lstr, ‘[^aeiou\s]o|[^aeiou\s]i’, ‘match’)

ans = ‘bo’ ‘co’ ‘ti’ ‘to’ ‘ri’

^expr 匹配 expr,并且出现在原字符串最前端的子串。expr$ 匹配 expr,并且出现在原字符串最末端的子串。

>>pi(lstr, ‘^a\w*|\w*s$’, ‘match’)

ans = ‘A’ ‘stories’

\> regexpi(lstr, ‘\匹配 expr,并且出现在一个单词最末端的子串。

>> regexpi(lstr, ‘\w*tion\>’, ‘match’)

ans = ‘collection’

\更严格的单词匹配,如:以 s 开头,并且以 h 结尾的单词。

>>regexpi(lstr, ‘\’, ‘match’)

ans = ‘such’

3.3 左顾右盼 —— 利用上下文匹配

利用上下文的匹配来找到我们要找的内容。expr1(?=expr2) 找到匹配 expr1 的子串,如果其后的字符串也匹配 expr2。如下面的例子查找所有在’,’之前的单词。

s=’Grammar Of, relating to, or being a noun or pronoun case that indicates possession.’;

ptn=’\w*(?=,)’;

regexp(s,ptn,’match’)

ans = ‘Of’ ‘to’

expr1(?!expr2) 找到匹配 expr1 的子串如果其后的字符串不匹配 expr2。下面的例子匹配所有不在’,’之前的单词:

>>regexpi(s, ‘\w*(?!=,)’, ‘match’)

ans = ‘Grammar’ ‘Of’ ‘relating’ ‘to’ ‘or’ ‘being’ ‘a’ ‘noun’ ‘or’

‘pronoun’ ‘case’ ‘that’ ‘indicates’ ‘possession’

(?>regexpi(s,'(?

ans = ‘relating’ ‘or’

(?>regexpi(s,'(?>mat

mat = ‘mm’ ‘ss’ ‘ss’

>>tok{:}

ans = ‘m’

ans = ‘s’

ans = ‘s’

>>ext{:}

ans = 4 4

ans = 75 75

ans = 78 78

4.2 如何使用标记?

(expr)记录所有匹配表达式的字符,并做为一个标记,以备后面使用。如上面的例子,利用标记实现查找连续的重复字母。

\N匹配同一条正则表达式里的第 N 个标记中的字符串,例如 \1 匹配第一个标记。下面的例子可以查找 html 语句中类似abc的部分:

hstr = ‘

Default
‘;

expr = ‘.*?’;

[mat tok] = regexp(hstr, expr, ‘match’, ‘tokens’);

>> mat{:}

ans =

ans =

Default

>> tok{:}

ans = ‘tr’

ans = ‘table’

$N 在一个替换字符串中插入与第 N 个标记相匹配的字符串(只用于 regexprep 函数)。下面的例子可以将匹配到的第一个 token 和第二个 token 的位置互换:

>> regexprep(‘Norma Jean Baker’, ‘(\w+\s\w+)\s(\w+)’, ‘$2, $1’)

ans = Baker, Norma Jean

(?expr) 记录所有匹配表达式 expr 的字符,做为一个标记,并设定一个名字 name。\k与名为 name 的标记相匹配。下面这个例子和这部分第一个例子是一样的,只不过使用了命名的标记。

>>poestr = [‘While I nodded, nearly napping, ‘ …

‘suddenly there came a tapping,’];

>>regexp(poestr, ‘(?\S)\k’, ‘match’)

ans = ‘dd’ ‘pp’ ‘dd’ ‘pp’

(?(tok)expr) 如果标记 tok 已经产生,则匹配表达式 expr。if-then 结构。其中的标记可以是数字标记,也可以是命名标记。 (?(tok)expr1|expr2) 如果标记 tok 已经产生,则匹配表达式 expr1,否则匹配表达式 expr2。if-then-else结构 下面的例子用来检查一个句子中的性别用词是否匹配,表达式的意思就是,如果前面用的是 ‘Mrs’ 那么后面就匹配 ‘her’,如果前面用的是’Mr’,也就是没有匹配到 ‘Mr’ 后面的 ‘s’,则后面匹配 ‘his’。

>>expr = ‘Mr(s?)\..*?(?(1)her|his) son’;

>>[mat tok] = regexp(‘Mr. Clark went to see his son’, expr, ‘match’, ‘tokens’)

mat = ‘Mr. Clark went to see his son’

tok = {1×2 cell}

>>tok{:}

ans = ” ‘his’

如果把句子中的 his 改成 her,则没有与之匹配的结果。

>>[mat tok] = regexp(‘Mr. Clark went to see her son’, expr, ‘match’, ‘tokens’)

mat = {}

tok = {}

5.多行字符串与多正则表达式

5.1 多字符串与单个正则表达式匹配

多个字符串存在一个元胞数组里之后,每一个字符串与正则表达式匹配,返回值的维数与元胞数组相同。

cstr = { …

‘Whose woods these are I think I know.’ ; …

‘His house is in the village though;’ ; …

‘He will not see me stopping here’ ; …

‘To watch his woods fill up with snow.’};

>>idx{:}

ans = % ‘Whose woods these are I think I know.’

8 % |8

ans = % ‘His house is in the village though;’

23 % |23

ans = % ‘He will not see me stopping here’

6 14 23 % |6 |14 |23

ans = % ‘To watch his woods fill up with snow.’

15 22 % |15 |22

5.2 多个字符串与多个正则表达式匹配

这种情况下,应该满足字符串元胞数组中字符串的个数和正则表达式的个数相等——但维数不一定要相等——如可以用 4*1 的元胞数组与 1*4 的正则表达式相匹配。

expr = {‘i\s’, ‘hou’, ‘(.)\1’, ‘\>s = regexprep(cstr, ‘(.)\1’, ‘–‘, ‘ignorecase’)

s = ‘Whose w–ds these are I think I know.’

‘His house is in the vi–age though;’

‘He wi– not s– me sto–ing here’

‘To watch his w–ds fi– up with snow.

6.应用实例

问题 1:查找包含某个字串的串。例如:在 str = {‘apple_food’ , ‘chocolates_food’, ‘ipod_electronics’, ‘dvd_player_electronics’, ‘water_melon_food’} 中查找字串’food’,得到结果 [1 1 0 0 1]。

str = {‘apple_food’ , ‘chocolates_food’, ‘ipod_electronics’, ‘dvd_player_electronics’, ‘water_melon_food’} ;

ptn=’food’;

m1=regexp(str,ptn,’match’);

ix=~cellfun(‘isempty’,m1);

问题 2:如何将 Matlab 中的 ^ 转换成 C 语言?如将 a^b 转换成 a**b,或者 pow(a,b)。以下式为例:

s=1/2*w/(1+Pf^2*Pc-Pf^2*Pc*w1-w1*Pf^2-Pf*Pc-Pf^2*w^2+2*w1*Pf-2*Pf)

Matlab 提供了 ccode 命令,用于将 Matlab 转换为 c,这里仅为一例:

s=’1/2*w/(1+Pf^2*Pc-Pf^2*Pc*w1-w1*Pf^2-Pf*Pc-Pf^2*w^2+2*w1*Pf-2*Pf)’;

ptn='(\w{1,2})\^(\d{1})’;

regexp(s,ptn,’tokens’);

s1=regexprep(s,ptn,[‘pow(‘,’$1′,’,’,’$2′,’)’])

问题 3:删掉和它们之间的部分,例如:

处理前:Hello world. 2 < 5

处理后:Hello world. 2 < 5

ss=’Hello world. 2 < 5′;

b=”;

sr=regexprep(ss,b,”)

问题 4:游程平滑算法:将连续的且个数小于某个阈值的 0 全部替换成 1,例如:

平滑前:1111100000111100011

平滑后:1111100000111111111

a = [1 0 0 1 0 0 0 0 1 1 1 1 1 0 0 0 0 0 1 1 1 1 0 0 0 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1];

T = 4;

b = sprintf(‘%d’,a);

b1 = regexprep(b,'(?

a1=b1-48

**********************************************

 

Matlab中定义类 | Matlab面向对象编程

使用Java和C++久了,编程就自然而然的使用面向对象的一些思想来思考。需要一些结构的时候,总是想要用类。

在matlab中也有这么一个东西可以来创建类。Matlab的帮助文件中,描述如下:

 
classdef

Class definition keywords
Syntax

classdef classname
properties
PropName
end
methods
methodName
end
events
EventName
end
enumeration
EnumName (arg)
end
end

Description

classdef classname begins the class definition, an end keyword terminates the classdef block. Only blank lines and comments can precede classdef. Enter a class definition in a file having the same name as the class, with a filename extension of .m. Class definition files can be in folders on the MATLAB path or in @ folders whose parent folder is on the MATLAB path. See Saving Class Files for more information. See Classdef Block and Class Syntax for more information on classes.

properties begins a property definition block, an end keyword terminates the properties block. Class definitions can contain multiple property definition blocks, each specifying different attribute settings that apply to the properties in that particular block. See Defining Properties for more information.

methods begins a methods definition block, an end keyword terminates the methods block. This block contains functions that implement class methods. Class definitions can contain multiple method blocks, each specifying different attribute settings that apply to the methods in that particular block. It is possible to define method functions in separate files. See How to Use Methods for more information.

events begins an events definition block, an end keyword terminates the events block. This block contains event names defined by the class. Class definitions can contain multiple event blocks, each specifying different attribute settings that apply to the events in that particular block. See Events and Listeners — Syntax and Techniques for more information.

enumeration begins an enumeration definition block, an end keyword terminates the enumeration block. See Enumerations for more information.

properties, methods, events, and enumeration are also the names of MATLAB functions used to query the respective class members for a given object or class name.

To see the attributes of all class components in a popup window, click this link: Attribute Tables
Examples

Use these keywords to define classes.
classdef (Attributes) class_name
properties (Attributes)
PropertyName
end
methods (Attributes)
function obj = methodName(obj,arg2,…)

end
end
events (Attributes)
EventName
end
enumeration
EnumName
end
end

See Also

Tutorials
Object-Oriented Programming Class Definition—Syntax Reference

 

描述的非常简洁易懂,并且附带了示例,真不错。

classdef关键词定义的类有四个段,properties,应该和Java类中的对象属性变量是一个意思;Methods自然就是类的一些方法;

events,类中的一些事件,在Java中一些事件的消息发送和事件处理往往是继承一些接口例如MouseEvent或者implements ActionListener来实现的。

Matlab这里是怎么做的,还需要再做研究。

下面给出一个类的例子:

sortrows (Matlab排序整个矩阵,根据一个序列同时排序另一个序列)

Syntax

B = sortrows(A)
B = sortrows(A,column)
[B,index] = sortrows(A,…)

 

sortrows对矩阵进行排序,同时保证每一行都是对应的,也就是同行的数值在排序结束之后也还是同行的数值。

输入矩阵:A

输出矩阵:B, 默认按照矩阵A的第一列的值,从小到大排序。

B = sortrows(A,n); 对A根据第n列按照从小到大的顺序排列,并返回给B.

B = sortrows(A,-n);对A根据第n列按照从大到小的顺序排列,并返回给B.

 

举几个小例子:

>> A = magic(5)

A =

17    24     1     8    15
23     5     7    14    16
4     6    13    20    22
10    12    19    21     3
11    18    25     2     9

>> B = sortrows(A,2) %对A  第2列 从小到大排序  保持每一行都还是同行

B =

23     5     7    14    16
4     6    13    20    22
10    12    19    21     3
11    18    25     2     9
17    24     1     8    15
>> B= sortrows(A,-3) % 第3列, 从大到小排序 …….

B =

11    18    25     2     9
10    12    19    21     3
4     6    13    20    22
23     5     7    14    16
17    24     1     8    15

 

屏蔽优酷视频片前广告

话说以前看视频不多,所以也没太在意每段视频前的广告,最近越发讨厌起这些广告了。因为优酷视频看得最多,所以首当其冲的自然是优酷了。原理很简 单,大型视频网站构架都对网站进行了细致的优化,图片、视频都保存在各自独立的服务器集群,而广告业务也有独立的服务器和二级域名,只要我们的浏览器访问 不到负责广告业务的服务器,自然就屏蔽了视频广告。

所以想要禁止浏览器访问制定域名服务器是件很简单的事情,只要修改host表将域名指向127.0.0.1。那么想屏蔽任何视频网站广告只要找到相应视频网站对应的广告服务器的二级域名就可以了。

以Windows为例( xp 与 7 均适用),用记事本打开这个文件:

C:\Windows\System32\drivers\etc\hosts

(如果是win 7用户,提示打开权限不够的话,可以先复制hosts文件到别处,然后再替换之,对于已解锁用户来讲无此烦恼。)

将下面的内容复制进去,保存即可,无需重启。

1 #优酷
2 127.0.0.1 atm.youku.com
3 127.0.0.1 fvid.atm.youku.com
4 127.0.0.1 html.atm.youku.com
5 127.0.0.1 valb.atm.youku.com
6 127.0.0.1 valf.atm.youku.com
7 127.0.0.1 valo.atm.youku.com
8 127.0.0.1 valp.atm.youku.com
9 127.0.0.1 Lstat.youku.com
10 127.0.0.1 speed.lstat.youku.com
11 127.0.0.1 urchin.lstat.youku.com
12 127.0.0.1 stat.youku.com
13 127.0.0.1 static.lstat.youku.com
14 127.0.0.1 valc.atm.youku.com
15 127.0.0.1 vid.atm.youku.com
16 127.0.0.1 walp.atm.youku.com
0

 爱奇异网和土豆网的广告也可以用类似的方法禁止哦~~~~~

在线学习服务Course Hero的创新:学习免费指导收费 提供实质性奖励

2012年的全国高考于近日结束,共有915万学生参加。虽然参与学生的绝对数量依然庞大,但是越来越多的学生开始放弃高考,过去四年中放弃高考的 学生总数已达300万。这一现象背后的根本原因是因为中国高校的学费随着KPI水涨船高,教育水平却由于持续扩招和教育资源的变质而不断下降,学生毕业即 失业成了常态,接受高等教育的投入产出比已趋近不正常,所以放弃高考的学生越来越多,此外更多的人开始相信“中国高校已死,中国高等教育已死”,其中更有 激进的人开始怀疑“知识改变命运”。

中国的高等教育确实存在各种问题,但是“知识改变命运”却是不容质疑的。以漂在北上广的年轻人的距离,在这三个关系背景不很重要的城市里,只要你不 断学习,不断努力,知识依旧能够使得你达成渴望中的成功,实现梦想,你我身边这样的例子不断地发生着和继续着。知识改变命运没有变,变的是获取知识的方 法。

所以,更便捷、更便宜的学习服务成为大势所趋。本人介绍一家位于美国加州红杉市的初创企业Course Hero,它于2008年成立,是一家提供教育服务的在线平台。Coures Hero整合了Youtube等视频网站上的教育资源,免费向使用者提供课程资源和相关的学习资料,并以收费的方式向使用者提供个性化的学习辅导,价格为 40美元一个月或95美元一年。同时,使用者也可以通过每月提供40份学习资料来获得免费服务。

Course Hero提供的每门课程范围极广,适合各年龄阶段、不同职业背景的人士学习。它的课程都分成数个章节,每个章节配有经过精心编排的视频、辅导资料。如果有 必要,你还可以提出建议或者自己动手创建课程。毫不例外,在Course Hero,各大社交网站的分享按钮也一应俱全。

Course Hero的网站分为多个板块:

  • 学习资料,包括极多的学习资料和课件,据报道它包含了全世界超过4300所大学院校的700万份资料,学生还能自己上传文档共享;
  • 导师服务,用户在学习过程中可以随时提出问题,并自主设定问题到期时间,Course Hero提供的专家可以随时为用户提供服务;
  • 课程学习,于今年春天上线,会给完成课程的用户以各种实质性的奖励,比如一个桶SV angel合作的课程,优胜者可以获得1250美元的奖金,以及同SV Angel的接触机会;
  • 学习卡片,这是Course Hero开发的便于用户学习的工具,它在正面写出名词,背面提供名词解释;
  • 视频课程,同可汗学院自己制作发布视频不同,Course Hero整合了来自于Youtube的大量视频。

在Course Hero,使用者每完成一个章节的学习,就会被要求参加随附的考试,并且在整个课程结束后有结课测试,通过考试的使用者可以获得由Course Hero奖励的分数和徽章。Course Hero通过这样的方式来保证使用者的学习质量。

Course Hero的CEOAndrew Grauer并不希望媒体将Course Hero的目标定义为取代传统的高等教育,因为Course Hero正式的课程服务刚于今年3月份推出,之前其提供的服务仅为辅导中介和资料补充,但即便这样,Course Hero也已从去年开始持续盈利,而且自从其推出课程服务后,其每日的浏览量已超过10万次。

正是看到了Course Hero的无限潜力,由SV Angel牵头的风投和天使们一共为这个目前仅有22名员工的公司注入了238万美元的资金,以期其快速发展,从而增加获得知识的新途径。

网站:http://www.coursehero.com/

若无注明,本站文章均为原创或编译,转载请注明:本文来自bukop.com (作者:Edward)

微笑识别

论文:Exploring Temporal Patterns in Classifying Frustrated and Delighted Smiles

Is there a difference between while people smile under frustration as opposed to being genuinely delighted? How do the classifiers perform on recognizing mental states such as frustration and delighted when acted, as well as when elicited? What can we infer from the results about data collected through natural means as opposed to asking people to act? How do humans perform in correctly labeling smiles elicited under frustrated and genuinely delighted? Can we develop automated systems to distinguish between frustrated smiles and delighted smiles that perform better or as good as their human counterpart? This paper attempts to answer all these questions through a series of studies.

Publications:

M. E. Hoque, D. J. McDuff, R. W Picard, Exploring Temporal Patterns towards Classifying Frustrated and Delighted Smiles, IEEE Transactions on Affective Computing, 2011. [under review]

M. E. Hoque, R. W. Picard, Acted vs. natural frustration and delight: Many people smile in natural frustration, 9th IEEE International Conference on Automatic Face and Gesture Recognition (FG’11), Santa Barbara, CA, USA, March 2011. (PDF: 1693 KB)

Press:

Specs that see right through you, by Sally Adee, NewScientist, July 5, 2011.

新闻来自:36kr

计算机面部识别技术虽然在近年并未获得突破性成果,但MIT的研究者还是在这方面取得一些不错成绩,他们最新开发的技术甚至能够判断微笑背后的真实情感。

研究人员最初让实验者表现出高兴与沮丧的表情,并使用两个摄像头记录图像。然后再让计算机算法与普通人同时对记录的表情进行情绪判断,两者都能基本 判别。再让本来就快乐的人与本来遭受了挫折的人都露出微笑表情时,人类通过笑容判别情绪的准确率过半,而MIT的计算机算法的差别准确率却能超过90%。

研究人员希望该技术能更好地帮助那些理解人类表情有困难的人。同时,它在商业方面也有着较大潜力,因为他们认为:“顾客对你微笑,表达的不一定就是满意,笑容背后的含义很重要。”

 

这篇文章比较感兴趣。这一周中有两天在做人脸,与这篇文章相关。我用的方法先透露一下:Gabor小波 + PCA主成份分析 –> 形成SVM分类器特征 –>训练SVM分类器 –> 人脸权限判别。下周实验结束之后,相关资料和编写的源代码以及实验数据都会上传到本博客。

决定开辟并收集IT方面的智力题

最近看程序员宝典,编程之美,编程珠玑等书籍,对里面的智力题目非常感兴趣。茶余饭后是常常和朋友相互提问探讨,以至于现在,见到一些场景也尝试自己原创一些题目。校园里面有几处健身器材,前些天饭后路过跷跷板,就想到了一个题目:十个人体重不同,但从身材无法分辨谁重谁轻,问通过这个跷跷板,最少经过几次能把十个人分成两个队伍,其中一个队伍的任何一个人都比另一个队伍的人更重。

很明显的,对十个人依次比较排队之后一定能够解决这个问题,但此方法一定不是最优方法,最优的方法是什么?

大家思考一下。任何见解都可以回复本帖,希望能热烈讨论

 

Matlab进行PCA一眼通

上篇转载文章,我们学习了PCA的原理。这篇文章,将单纯说一下PCA在matlab中如何进行。0难度,一眼通。

假设矩阵temp中存放我们的特征向量矩阵。每一个向量是n维的,有m个样本。那么temp就是m*n维度的矩阵。其中每一行表示一个样本的特征向量。

matlab使用下句进行主成份分析(PCA)

[coef,score,latent] = princomp(temp);

返回参数: coef维度n*n,是上篇文章中的V(右奇异矩阵)。 score是temp特征向量矩阵投射到coef正交基底上的系数,latent是各个正交基底对应的特征值组成的向量(或者说每一个成分的能量值)。

score  约=  temp*coef;

想要把一个新的特征 f (1*n维度) 投射到coef空间仅仅通过:

f*coef就可以了。

 

如果想降维怎么办?如果想把n维向量降维到r维(r<n)。那么coef仅仅保留前r列,由coef(n*n维度)变成coef(n*r维度)也就可以了。

这样 f*coef得到的结果向量维度为  1*n  *  n*r  -> 1*r  就把一个1*n维度的向量变化到了1*r维度了。

 

总之:[coef,score,latent] = princomp(temp);

然后coef仅仅保留前r列记为coef_r。

featurevector* coef_r 就是降维后的特征了。

leftnoteasy:大的矩阵奇异值分解(SVD)及其应用[转]

前言:

上一次写了关于PCA与LDA的 文章,PCA的实现一般有两种,一种是用特征值分解去实现的,一种是用奇异值分解去实现的。在上篇文章中便是基于特征值分解的一种解释。特征值和奇异值在 大部分人的印象中,往往是停留在纯粹的数学计算中。而 且线性代数或者矩阵论里面,也很少讲任何跟特征值与奇异值有关的应用背景。奇异值分解是一个有着很明 显的物理意义的一种方法,它可以将一个比较复杂的矩阵用更小更简单的几个子矩阵的相乘来表示,这些小矩阵描述的是矩阵的重要的特性。就像是描述一个人一 样,给别人描述说这个人长得浓眉大眼,方脸,络腮胡,而且带个黑框的眼镜,这样寥寥的几个特征,就让别人脑海里面就有一个较为清楚的认识,实际上,人脸上 的特征是有着无数种的,之所以能这么描述,是因为人天生就有着非常好的抽取重要特征的能力,让机器学会抽取重要的特征,SVD是一个重要的方法。

在机器学习领域,有相当多的应用与奇异值都可以扯上关系,比如做feature reduction的PCA,做数据压缩(以图像压缩为代表)的算法,还有做搜索引擎语义层次检索的LSI(Latent Semantic Indexing)

另外在这里抱怨一下,之前在百度里面搜索过SVD,出来的结果都是俄罗斯的一种狙击枪(AK47同时代的),是因为穿越火线这个游戏里面有一把狙击 枪叫做 SVD,而在Google上面搜索的时候,出来的都是奇异值分解(英文资料为主)。想玩玩战争游戏,玩玩COD不是非常好吗,玩山寨的CS有神马意思啊。 国内的网页中的话语权也被这些没有太多营养的帖子所占据。真心希望国内的气氛能够更浓一点,搞游戏的人真正是喜欢制作游戏,搞Data Mining的人是真正喜欢挖数据的,都不是仅仅为了混口饭吃,这样谈超越别人才有意义,中文文章中,能踏踏实实谈谈技术的太少了,改变这个状况,从我自 己做起吧。

前面说了这么多,本文主要关注奇异值的一些特性,另外还会稍稍提及奇异值的计算,不过本文不准备在如何计算奇异值上展开太多。另外,本文里面有部分不算太深的线性代数的知识,如果完全忘记了线性代数,看本文可能会有些困难。

一、奇异值与特征值基础知识:

特征值分解和奇异值分解在机器学习领域都是属于满地可见的方法。两者有着很紧密的关系,我在接下来会谈到,特征值分解和奇异值分解的目的都是一样,就是提取出一个矩阵最重要的特征。先谈谈特征值分解吧:

1)特征值:

如果说一个向量v是方阵A的特征向量,将一定可以表示成下面的形式:

image

这时候λ就被称为特征向量v对应的特征值,一个矩阵的一组特征向量是一组正交向量。特征值分解是将一个矩阵分解成下面的形式:

image

其中Q是这个矩阵A的特征向量组成的矩阵,Σ是一个对角阵,每一个对角线上的元素就是一个特征值。我这里引用了一些参考文献中的内容来说明一下。首 先,要 明确的是,一个矩阵其实就是一个线性变换,因为一个矩阵乘以一个向量后得到的向量,其实就相当于将这个向量进行了线性变换。比如说下面的一个矩阵:

image 它其实对应的线性变换是下面的形式:

image 因为这个矩阵M乘以一个向量(x,y)的结果是:

image 上面的矩阵是对称的,所以这个变换是一个对x,y轴的方向一个拉伸变换(每一个对角线上的元素将会对一个维度进行拉伸变换,当值>1时,是拉长,当值<1时时缩短),当矩阵不是对称的时候,假如说矩阵是下面的样子:

image

它所描述的变换是下面的样子:

image

这其实是在平面上对一个轴进行的拉伸变换(如蓝色的箭头所示),在图中,蓝色的箭头是一个最主要的变化方向(变化方向可能有不止一个),如果我们想要描述好一个变换,那我们就描述好这个变换主要的变化方向就好了。反过头来看看之前特征值分解的式子,分解得到的Σ矩阵是一个对角阵,里面的特征值是由大到小排列的,这些特征值所对应的特征向量就是描述这个矩阵变化方向(从主要的变化到次要的变化排列)

当矩阵是高维的情况下,那么这个矩阵就是高维空间下的一个线性变换,这个线性变化可能没法通过图片来表示,但是可以想象,这个变换也同样有很多的变 换方 向,我们通过特征值分解得到的前N个特征向量,那么就对应了这个矩阵最主要的N个变化方向。我们利用这前N个变化方向,就可以近似这个矩阵(变换)。也就 是之前说的:提取这个矩阵最重要的特征。总结一下,特征值分解可以得到特征值与特征向量,特征值表示的是这个特征到底有多重要,而特征向量表示这个特征是什么,可以将每一个特征向量理解为一个线性的子空间,我们可以利用这些线性的子空间干很多的事情。不过,特征值分解也有很多的局限,比如说变换的矩阵必须是方阵。

(说了这么多特征值变换,不知道有没有说清楚,请各位多提提意见。)

2)奇异值:

下面谈谈奇异值分解。特征值分解是一个提取矩阵特征很不错的方法,但是它只是对方阵而言的,在现实的世界中,我们看到的大部分矩阵都不是方阵,比如说有N个学生,每个学生有M科成绩,这样形成的一个N * M的矩阵就不可能是方阵,我们怎样才能描述这样普通的矩阵呢的重要特征呢?奇异值分解可以用来干这个事情,奇异值分解是一个能适用于任意的矩阵的一种分解的方法

image 假设A是一个N * M的矩阵,那么得到的U是一个N * N的方阵(里面的向量是正交的,U里面的向量称为左奇异向量),Σ是一个N * M的矩阵(除了对角线的元素都是0,对角线上的元素称为奇异值),V’(V的转置)是一个N * N的矩阵,里面的向量也是正交的,V里面的向量称为右奇异向量),从图片来反映几个相乘的矩阵的大小可得下面的图片

image

那么奇异值和特征值是怎么对应起来的呢?首先,我们将一个矩阵A的转置 * A,将会得到一个方阵,我们用这个方阵求特征值可以得到:image 这里得到的v,就是我们上面的右奇异向量。此外我们还可以得到:

image 这里的σ就是上面说的奇异值,u就是上面说的左奇异向量。奇异值σ跟特征值类似,在矩阵Σ中也是从大到小排列,而且σ的减少特别的快,在很多情况下,前10%甚至1%的奇异值的和就占了全部的奇异值之和的99%以上了。也就是说,我们也可以用前r大的奇异值来近似描述矩阵,这里定义一下部分奇异值分解

image

r是一个远小于m、n的数,这样矩阵的乘法看起来像是下面的样子:

image

右边的三个矩阵相乘的结果将会是一个接近于A的矩阵,在这儿,r越接近于n,则相乘的结果越接近于A。而这三个矩阵的面积之和(在存储观点来说,矩 阵面积 越小,存储量就越小)要远远小于原始的矩阵A,我们如果想要压缩空间来表示原矩阵A,我们存下这里的三个矩阵:U、Σ、V就好了。

二、奇异值的计算:

奇异值的计算是一个难题,是一个O(N^3)的算法。在单机的情况下当然是没问题的,matlab在一秒钟内就可以算出1000 * 1000的矩阵的所有奇异值,但是当矩阵的规模增长的时候,计算的复杂度呈3次方增长,就需要并行计算参与了。Google的吴军老师在数学之美系列谈到SVD的时候,说起Google实现了SVD的并行化算法,说这是对人类的一个贡献,但是也没有给出具体的计算规模,也没有给出太多有价值的信息。

其实SVD还是可以用并行的方式去实现的,在解大规模的矩阵的时候,一般使用迭代的方法,当矩阵的规模很大(比如说上亿)的时候,迭代的次数也可能 会上亿 次,如果使用Map-Reduce框架去解,则每次Map-Reduce完成的时候,都会涉及到写文件、读文件的操作。个人猜测Google云计算体系中 除了Map-Reduce以外应该还有类似于MPI的计算模型,也就是节点之间是保持通信,数据是常驻在内存中的,这种计算模型比Map-Reduce在 解决迭代次数非常多的时候,要快了很多倍。

Lanczos迭代就是一种解对称方阵部分特征值的 方法(之前谈到了,解A’* A得到的对称方阵的特征值就是解A的右奇异向量),是将一个对称的方程化为一个三对角矩阵再进行求解。按网上的一些文献来看,Google应该是用这种方 法去做的奇异值分解的。请见Wikipedia上面的一些引用的论文,如果理解了那些论文,也“几乎”可以做出一个SVD了。

由于奇异值的计算是一个很枯燥,纯数学的过程,而且前人的研究成果(论文中)几乎已经把整个程序的流程图给出来了。更多的关于奇异值计算的部分,将在后面的参考文献中给出,这里不再深入,我还是focus在奇异值的应用中去。

三、奇异值与主成分分析(PCA):

主成分分析在上一节里面也讲了一些,这里主要谈谈如何用SVD去解PCA的问题。PCA的问题其实是一个基的变换,使得变换后的数据有着最大的方 差。方差 的大小描述的是一个变量的信息量,我们在讲一个东西的稳定性的时候,往往说要减小方差,如果一个模型的方差很大,那就说明模型不稳定了。但是对于我们用于 机器学习的数据(主要是训练数据),方差大才有意义,不然输入的数据都是同一个点,那方差就为0了,这样输入的多个数据就等同于一个数据了。以下面这张图 为例子:

image 这个假设是一个摄像机采集一个物体运动得到的图片,上面的点表示物体运动的位置,假如我们想要用一条直线去拟合这些点,那我们会选择什么方向的线呢?当然 是图上标有signal的那条线。如果我们把这些点单纯的投影到x轴或者y轴上,最后在x轴与y轴上得到的方差是相似的(因为这些点的趋势是在45度左右 的方向,所以投影到x轴或者y轴上都是类似的),如果我们使用原来的xy坐标系去看这些点,容易看不出来这些点真正的方向是什么。但是如果我们进行坐标系 的变化,横轴变成了signal的方向,纵轴变成了noise的方向,则就很容易发现什么方向的方差大,什么方向的方差小了。

一般来说,方差大的方向是信号的方向,方差小的方向是噪声的方向,我们在数据挖掘中或者数字信号处理中,往往要提高信号与噪声的比例,也就是信噪比。对上图来说,如果我们只保留signal方向的数据,也可以对原数据进行不错的近似了。

PCA的全部工作简单点说,就是对原始的空间中顺序地找一组相互正交的坐标轴,第一个轴是使得方差最大的,第二个轴是在与第一个轴正交的平面中使得 方差最 大的,第三个轴是在与第1、2个轴正交的平面中方差最大的,这样假设在N维空间中,我们可以找到N个这样的坐标轴,我们取前r个去近似这个空间,这样就从 一个N维的空间压缩到r维的空间了,但是我们选择的r个坐标轴能够使得空间的压缩使得数据的损失最小。

还是假设我们矩阵每一行表示一个样本,每一列表示一个feature,用矩阵的语言来表示,将一个m * n的矩阵A的进行坐标轴的变化,P就是一个变换的矩阵从一个N维的空间变换到另一个N维的空间,在空间中就会进行一些类似于旋转、拉伸的变化。

image

而将一个m * n的矩阵A变换成一个m * r的矩阵,这样就会使得本来有n个feature的,变成了有r个feature了(r < n),这r个其实就是对n个feature的一种提炼,我们就把这个称为feature的压缩。用数学语言表示就是:

image 但是这个怎么和SVD扯上关系呢?之前谈到,SVD得出的奇异向量也是从奇异值由大到小排列的,按PCA的观点来看,就是方差最大的坐标轴就是第一个奇异向量,方差次大的坐标轴就是第二个奇异向量…我们回忆一下之前得到的SVD式子:

image 在矩阵的两边同时乘上一个矩阵V,由于V是一个正交的矩阵,所以V转置乘以V得到单位阵I,所以可以化成后面的式子

image 将后面的式子与A * P那个m * n的矩阵变换为m * r的矩阵的式子对照看看,在这里,其实V就是P,也就是一个变化的向量。这里是将一个m * n 的矩阵压缩到一个m * r的矩阵,也就是对列进行压缩,如果我们想对行进行压缩(在PCA的观点下,对行进行压缩可以理解为,将一些相似的sample合并在一起,或者将一些没 有太大价值的sample去掉)怎么办呢?同样我们写出一个通用的行压缩例子:

image 这样就从一个m行的矩阵压缩到一个r行的矩阵了,对SVD来说也是一样的,我们对SVD分解的式子两边乘以U的转置U’

image 这样我们就得到了对行进行压缩的式子。可以看出,其实PCA几乎可以说是对SVD的一个包装,如果我们实现了SVD,那也就实现了PCA了,而且更好的地 方是,有了SVD,我们就可以得到两个方向的PCA,如果我们对A’A进行特征值的分解,只能得到一个方向的PCA。

四、奇异值与潜在语义索引LSI:

潜在语义索引(Latent Semantic Indexing)与PCA不太一样,至少不是实现了SVD就可以直接用的,不过LSI也是一个严重依赖于SVD的算法,之前吴军老师在矩阵计算与文本处理中的分类问题中谈到:

“三个矩阵有非常清楚的物理含义。第一个矩阵X中的每一行表示意思相关的一类词,其中的每个非零元素表示这类词中每个词的重要性(或者说相关性),数值越 大越相关。最后一个矩阵Y中的每一列表示同一主题一类文章,其中每个元素表示这类文章中每篇文章的相关性。中间的矩阵则表示类词和文章雷之间的相关性。因 此,我们只要对关联矩阵A进行一次奇异值分解,w 我们就可以同时完成了近义词分类和文章的分类。(同时得到每类文章和每类词的相关性)。”

上面这段话可能不太容易理解,不过这就是LSI的精髓内容,我下面举一个例子来说明一下,下面的例子来自LSA tutorial,具体的网址我将在最后的引用中给出:

image 这就是一个矩阵,不过不太一样的是,这里的一行表示一个词在哪些title中出现了(一行就是之前说的一维feature),一列表示一个title中有 哪些词,(这个矩阵其实是我们之前说的那种一行是一个sample的形式的一种转置,这个会使得我们的左右奇异向量的意义产生变化,但是不会影响我们计算 的过程)。比如说T1这个title中就有guide、investing、market、stock四个词,各出现了一次,我们将这个矩阵进行SVD, 得到下面的矩阵:

image 左奇异向量表示词的一些特性,右奇异向量表示文档的一些特性,中间的奇异值矩阵表示左奇异向量的一行与右奇异向量的一列的重要程序,数字越大越重要。

继续看这个矩阵还可以发现一些有意思的东西,首先,左奇异向量的第一列表示每一个词的出现频繁程度,虽然不是线性的,但是可以认为是一个大概的描 述,比如 book是0.15对应文档中出现的2次,investing是0.74对应了文档中出现了9次,rich是0.36对应文档中出现了3次;

其次,右奇异向量中一的第一行表示每一篇文档中的出现词的个数的近似,比如说,T6是0.49,出现了5个词,T2是0.22,出现了2个词。

然后我们反过头来看,我们可以将左奇异向量和右奇异向量都取后2维(之前是3维的矩阵),投影到一个平面上,可以得到:

image 在图上,每一个红色的点,都表示一个词,每一个蓝色的点,都表示一篇文档,这样我们可以对这些词和文档进行聚类,比如说stock 和 market可以放在一类,因为他们老是出现在一起,real和estate可以放在一类,dads,guide这种词就看起来有点孤立了,我们就不对他 们进行合并了。按这样聚类出现的效果,可以提取文档集合中的近义词,这样当用户检索文档的时候,是用语义级别(近义词集合)去检索了,而不是之前的词的级 别。这样一减少我们的检索、存储量,因为这样压缩的文档集合和PCA是异曲同工的,二可以提高我们的用户体验,用户输入一个词,我们可以在这个词的近义词 的集合中去找,这是传统的索引无法做到的。

不知道按这样描述,再看看吴军老师的文章,是不是对SVD更清楚了?:-D

参考资料:

1)A Tutorial on Principal Component Analysis, Jonathon Shlens
这是我关于用SVD去做PCA的主要参考资料
2)http://www.ams.org/samplings/feature-column/fcarc-svd
关于svd的一篇概念好文,我开头的几个图就是从这儿截取的
3)http://www.puffinwarellc.com/index.php/news-and-articles/articles/30-singular-value-decomposition-tutorial.html
另一篇关于svd的入门好文
4)http://www.puffinwarellc.com/index.php/news-and-articles/articles/33-latent-semantic-analysis-tutorial.html
svd与LSI的好文,我后面LSI中例子就是来自此
5)http://www.miislita.com/information-retrieval-tutorial/svd-lsi-tutorial-1-understanding.html
另一篇svd与LSI的文章,也还是不错,深一点,也比较长
6)Singular Value Decomposition and Principal Component Analysis, Rasmus Elsborg Madsen, Lars Kai Hansen and Ole Winther, 2004
跟1)里面的文章比较类似

====

本文由LeftNotEasy发布于http://leftnoteasy.cnblogs.com, 本文可以被全部的转载或者部分使用,但请注明出处,如果有问题,请联系wheeleast@gmail.com

C++ Socket编程步骤

sockets(套接字)编程有三种,流式套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM),原始套接字(SOCK_RAW);基于TCP的socket编程是采用的流式套接字。

服务器端编程的步骤:

1:加载套接字库,创建套接字(WSAStartup()/socket());

2:绑定套接字到一个IP地址和一个端口上(bind());

3:将套接字设置为监听模式等待连接请求(listen());

4:请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept());

5:用返回的套接字和客户端进行通信(send()/recv());

6:返回,等待另一连接请求;

7:关闭套接字,关闭加载的套接字库(closesocket()/WSACleanup())。

客户端编程的步骤:

1:加载套接字库,创建套接字(WSAStartup()/socket());

2:向服务器发出连接请求(connect());

3:和服务器端进行通信(send()/recv());

4:关闭套接字,关闭加载的套接字库(closesocket()/WSACleanup())。

第一式: 加载/释放Winsock库:

1.加载方法:

WSADATA wsa;
/*初始化socket资源*/
if (WSAStartup(MAKEWORD(1,1),&wsa) != 0)
{
return;   //代表失败
}

2.释放方法:

WSACleanup();

第二式: 构造SOCKET:

1.服务端:构造监听SOCKET,流式SOCKET.
SOCKET Listen_Sock = socket(AF_INET, SOCK_STREAM, 0)

2.客户端:构造通讯SOCKET,流式SOCKET.
SOCKET Client_Sock = socket(AF_INET, SOCK_STREAM, 0)

第三式:配置监听地址和端口:

1.服务端: SOCKADDR_IN serverAddr
ZeroMemory((char *)&serverAddr,sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(1234);           /*本地监听端口:1234*/
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); /*有IP*/

第四式:   绑定SOCKET:

1.服务端:绑定监听SOCKET.
  bind(Listen_Sock,(struct sockaddr *)&serverAddr,sizeof(serverAddr))

第五式: 服务端/客户端连接:

1.服务端:等待客户端接入.
SOCKET Command_Sock = accept(Listen_Sock, …)

2.客户端:请求与服务端连接.
int ret = connect(Client_Sock, …)

第六式: 收/发数据:

1.服务端:等待客户端接入.char buf[1024].
接收数据:recv(Command_Sock,buf, …)

发送数据:send(Command_Sock,buf, …)

2.客户端:请求与服务端连接.char buf[1024].
发送数据:send(Client_Sock,buf, …)

接收数据:recv(Client_Sock,buf, …)

第七式: 关闭SOCKET:

1.服务端:关闭SOCKET.
closesocket(Listen_Sock)
closesocket(Command_Sock)

2.客户端:关闭SOCKET.
closesocket(Client_Sock)

#include <stdio.h>
#include <Winsock2.h>
void main()
{
 WORD wVersionRequested;
 WSADATA wsaData;
 int err;
 
 wVersionRequested = MAKEWORD( 1, 1 );
 
 err = WSAStartup( wVersionRequested, &wsaData );
 if ( err != 0 ) {
  return;
 }
 
 if ( LOBYTE( wsaData.wVersion ) != 1 ||
        HIBYTE( wsaData.wVersion ) != 1 ) {
  WSACleanup( );
  return;
 }
 SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0);
 SOCKADDR_IN addrSrv;
 addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
 addrSrv.sin_family=AF_INET;
 addrSrv.sin_port=htons(6000);
 
 bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
 listen(sockSrv,5);
 SOCKADDR_IN addrClient;
 int len=sizeof(SOCKADDR);
 while(1)
 {
  SOCKET sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len);
  char sendBuf[50];
  sprintf(sendBuf,"Welcome %s to here!",inet_ntoa(addrClient.sin_addr));
  send(sockConn,sendBuf,strlen(sendBuf)+1,0);
  char recvBuf[50];
  recv(sockConn,recvBuf,50,0);
  printf("%s\n",recvBuf);
  closesocket(sockConn);
 }
}
#include <stdio.h>
#include <Winsock2.h>
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;wVersionRequested = MAKEWORD( 1, 1 );err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return;
}

if ( LOBYTE( wsaData.wVersion ) != 1 ||
HIBYTE( wsaData.wVersion ) != 1 ) {
WSACleanup( );
return;
}
SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);

SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr=inet_addr(“127.0.0.1″);
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(6000);
connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
send(sockClient,”hello”,strlen(“hello”)+1,0);
char recvBuf[50];
recv(sockClient,recvBuf,50,0);
printf(“%s\n”,recvBuf);

closesocket(sockClient);
WSACleanup();
}

复制代码
from: http://www.cnblogs.com/Sniper-quay/archive/2011/06/22/2086636.html