0%

在此之前没有接触过矩阵化运算,因此对于矩阵化运算的过程一头雾水。准备对于线性回归的代价函数进行矩阵化以探究其过程。


CostFuction 数学表达式:

\[J(\theta)=\frac{1}{2m}\sum^m_{i=1}(h_\theta(x^{(i)})-y^{(i)})^2\]

根据数学式之前以for循环写了算法:

1
2
3
4
for i=1:m
J += (theta(1)+ theta(2)*X(i,2)-y(i))^2;
end
J = J/(2*m);

很明确的循环符合数学式。

尝试对齐进行矩阵化,首先看\(h_\theta(x^{(i)})\)

\[h_\theta(x)=\theta^T x = \theta_0 + \theta_1 x_1\]

对每个x(i)进行运算:

upload successful

对其进行sum与转置操作后可以得到

\[\sum((\theta'.*X)')-y'= \\ [\theta_1 x^{(1)}_1+\theta_2 x^{(1)}_2 -y^{(1)},\theta_1 x^{(2)}_1+\theta_2 x^{(2)}_2 -y^{(2)},...,\theta_1 x^{(m)}_1+\theta_2 x^{(m)}_2 -y^{(m)}]\]

因此可以得知代价函数的矩阵化函数式为:

1
J = sum((sum((theta'.*X)')-y').^2)/(2*m);

之前页面只需要传一个值,因此用的是比较简单的方法:获取页面url后以等号进行字符串分割,代码如下:

1
2
var url = window.location.search;
var loc = url.substring(url.lastIndexOf("=") + 1, url.length);

但是这样只能获取最后一个等号所带的值,大多情况无法满足需要。因此需要一个能够获取全部参数部分(“?”之后的部分)

1
2
3
4
5
6
7
8
9
10
11
12
function GetRequest() {
var url = location.search; //获取url中"?"符后的字串
var theRequest = new Object();//新建对象
if (url.indexOf("?") != -1) { //排除没有参数的情况
var str = url.substr(1);//抽取从第二个字符到结尾的字符子串
strs = str.split("&");//将str以&作为分隔符分成多个部分,以数组形式存在strs里
for (var i = 0; i < strs.length; i++) {//遍历strs数组
theRequest[strs[i].split("=")[0]] = unescape(strs[i].split("=")[1]);//使theRsquest[key] = value
}
}
return theRequest;
}

使用方法:

GetRequest()[key]

例如 访问test.html?id=9&type=cat

在test.html里

GetRequest()["id"] //9

GetRequest()["type"] //cat

在实际项目中,需要制作"我的订单"功能。功能逻辑如下:使用ajax将所有订单数据下载到json数组中,将json数组与div绑定。

且订单有多个状态,如state=1是待确认订单,state=2是待付款订单,state=3是待配送订单,state=4是待评价订单。

但是在调支付接口时,发现已付款订单有两种状态:同步状态与异步状态(交易平台需要一定时间确认后才能将确认消息异步发送给服务端),为了用户体验,拟使同步与异步状态的订单都归类在“已付款订单”中,因此Vue原生自带的单个数值搜索的过滤器不足以满足需求,需要一个能够同时搜索多个数值的过滤器来进行过滤。

过滤器代码如下:

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
/**
* Filter filter array for arrays
*
* @param {String} arr
* @param {String} searcharr
* @param {String} feature
*/

function filtersBy(arr, searcharr, feature) {
searcharr = convertArray(searcharr);
arr = convertArray(arr);
var res = [];
var item, searchitem;
for (var i = 0; i < arr.length; i++) {
for (var j = 0; j < searcharr.length; j++) {
item = arr[i];
searchitem = searcharr[j];
console.log(feature)
if (item[feature] == searchitem) {
res.push(item);
}
}
}
return res;
}

插入源码后注册即可。

1
2
3
4
5
6
var filters = {
orderBy: orderBy,
filterBy: filterBy,
filtersBy: filtersBy,
limitBy: limitBy
}

运行效果:

数据:

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
var DATA = {
"datas": [{
"id": 1,
"type": 1,
"data": "这是分类一的第一项"
}, {
"id": 2,
"type": 1,
"data": "这是分类一的第二项"
}, {
"id": 3,
"type": 1,
"data": "这是分类一的第三项"
}, {
"id": 4,
"type": 2,
"data": "这是分类二的第一项"
}, {
"id": 5,
"type": 2,
"data": "这是分类二的第二项"
}, {
"id": 6,
"type": 3,
"data": "这是分类三的第一项"
}, {
"id": 7,
"type": 3,
"data": "这是分类三的第二项"
}, {
"id": 8,
"type": 3,
"data": "这是分类三的第三项"
}, {
"id": 9,
"type": 3,
"data": "这是分类三的第四项"
}]
}

html:

1
2
3
<div id="type-1">
<li v-for="data in datas | filtersBy '[2,3]' 'type'" track-by="item.id">{{data.data}}</li>
</div>

js:

1
2
3
4
var list = new Vue({
el: '#type-1',
data: DATA
})

结果:

upload successful

可以满足需求,在数据中搜索多项并过滤。

从左到右遍历数组的一种方式

arr.reduce(callback(previousValue,currentValue,index,array), [initialValue]);

callback 函数中 previousValue 等于 initialValue 的值或者是上一次 reduce return 回来的值

currentValue 是当前执行到的数组的值

index 是当前执行到的数组的下标

array 是执行 reducearray

尝试:

1
2
3
4
5
6
var a = [1,2,3,4,5,6]
a.reduce(
function(a,b,c,d){
console.log( 'previousValue= '+a+ ';currentValue= '+b+ ';index= '+c+ ';array= '+d)
return a
},[1,2,3,4])

得到结果

1
2
3
4
5
6
7
8
9
10
11
previousValue=1,2,3,4;currentValue=1;index=0;array=1,2,3,4,5,6

previousValue=1,2,3,4;currentValue=2;index=1;array=1,2,3,4,5,6

previousValue=1,2,3,4;currentValue=3;index=2;array=1,2,3,4,5,6

previousValue=1,2,3,4;currentValue=4;index=3;array=1,2,3,4,5,6

previousValue=1,2,3,4;currentValue=5;index=4;array=1,2,3,4,5,6

previousValue=1,2,3,4;currentValue=6;index=5;array=1,2,3,4,5,6

可以感受到其用法。

例如数组累加:

1
2
3
var a = [2,4,6,1]
sum = a.reduce(function(prev,cur){return prev+cur})
//sum = 13
* * *

因此vuejs中filterBy代码中的

1
2
3
var keys=toArray(arguments,n).reduce(function(prev,cur) {
return prev.concat(cur);
},[]);

用途是将数组扁平化。

例如

1
2
3
4
5
6
7
8
9
var a= [
[1, 2],
[3, 4],
[5, 6]
];
var b= a.reduce(function (prev, cur) {
return prev.concat(cur);
});
//b = [1,2,3,4,5,6]

设置一组json数据

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
var DATA = {
"datas": [{
"id": 1,
"type": 1,
"data": "这是分类一的第一项"
}, {
"id": 2,
"type": 1,
"data": "这是分类一的第二项"
}, {
"id": 3,
"type": 1,
"data": "这是分类一的第三项"
}, {
"id": 4,
"type": 2,
"data": "这是分类二的第一项"
}, {
"id": 5,
"type": 2,
"data": "这是分类二的第二项"
}, {
"id": 6,
"type": 3,
"data": "这是分类三的第一项"
}, {
"id": 7,
"type": 3,
"data": "这是分类三的第二项"
}, {
"id": 8,
"type": 3,
"data": "这是分类三的第三项"
}, {
"id": 9,
"type": 3,
"data": "这是分类三的第四项"
}]
}

并进行列表的双向绑定,加上过滤器选择type为1的项。

1
2
3
4
var list = new Vue({
el:'#type-1',
data:DATA
})
1
2
3
<div id="type-1">
<li v-for="data in datas|filterBy '1' in 'type'">{{data.data}}</li>
</div>

可以看到结果是

blob.png

显然过滤器发挥了作用。在vuejs源码中可以看到filterby函数的代码如下

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
/**
* Filter filter for arrays
*
* @param {String} search
* @param {String} [delimiter]
* @param {String} ...dataKeys
*/

function filterBy(arr, search, delimiter){
arr = convertArray(arr);
if (search == null){
return arr;
} //如果没有指定过滤中搜索的值,则将arr原样返回
if (typeof search === 'function'){ //“===”means 严格等于
return arr.filter(search); //在arr中直接用原生filter过滤出search的项
}
search = ('' + search).toLowerCase();//toLowerCase 将String转换为小写字符串
var n = delimiter === 'in' ? 3 : 2;//x?y:z 若x为true,结果显示y,若x为false,则结果显示z。
//如果delimiter是in,则n=3,否则n=2
var keys=toArray(arguments,n).reduce(function(prev,cur) {
return prev.concat(cur);//concat用于连接数组的值或具体的值。
},[]);//见reduce用法
var res = [];
var item,key,val,j;
for (var i = 0, l = arr.length; i < l; i++) {//遍历arr
item=arr[i];
val=item&&item.$value||item;
j=keys.length;
if(j){
while (j--) {
key = keys[j];
if (key === '$key' && contains$1(item.$key, search) || contains$1(getPath(val,key),search)) {
//如果在item中的delimiter找到了search,则将这个item放到res数组中
res.push(item);
break;
}
}
}else if (contains$1(item,search)) {//遍历item各级搜索search,如果有则放入res
res.push(item);
}
}
return res;//返回结果
}
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
/**
* String contain helper
*
* @param {*} val
* @param {String} search
*/

function contains$1(val, search) {
var i;
if (isPlainObject(val)) {
var keys = Object.keys(val);
i = keys.length;
while (i--) {
if (contains$1(val[keys[i]], search)) {
return true;
}
}
} else if (isArray(val)) {
i = val.length;
while (i--) {
if (contains$1(val[i], search)) {
return true;
}
}
} else if (val != null) {
return val.toString().toLowerCase().indexOf(search) > -1;
}
}

转自http://blog.csdn.net/wxdzxl/article/details/8502119

首先,== equality 等同,=== identity 恒等。 ==, 两边值类型不同的时候,要先进行类型转换,再比较。 ===,不做类型转换,类型不同的一定不等。

下面分别说明: 先说 ===,这个比较简单。下面的规则用来判断两个值是否===相等: 1、如果类型不同,就[不相等] 2、如果两个都是数值,并且是同一个值,那么[相等];(!例外)的是,如果其中至少一个是NaN,那么[不相等]。(判断一个值是否是NaN,只能用isNaN()来判断) 3、如果两个都是字符串,每个位置的字符都一样,那么[相等];否则[不相等]。 4、如果两个值都是true,或者都是false,那么[相等]。 5、如果两个值都引用同一个对象或函数,那么[相等];否则[不相等]。 6、如果两个值都是null,或者都是undefined,那么[相等]。 再说 ==,根据以下规则: 1、如果两个值类型相同,进行 === 比较。 2、如果两个值类型不同,他们可能相等。根据下面规则进行类型转换再比较: a、如果一个是null、一个是undefined,那么[相等]。 b、如果一个是字符串,一个是数值,把字符串转换成数值再进行比较。 c、如果任一值是 true,把它转换成 1 再比较;如果任一值是 false,把它转换成 0 再比较。 d、如果一个是对象,另一个是数值或字符串,把对象转换成基础类型的值再比较。对象转换成基础类型,利用它的toString或者valueOf方法。js核心内置类,会尝试valueOf先于toString;例外的是Date,Date利用的是toString转换。非js核心的对象,令说(比较麻烦,我也不大懂) e、任何其他组合,都[不相等]。

举例: "1" == true 类型不等,true会先转换成数值 1,现在变成 "1" == 1,再把"1"转换成 1,比较 1 == 1, 相等。

= 赋值运算符 == 等于 === 严格等于 例: var a = 3; var b = "3";

a==b 返回 true a===b 返回 false

因为a,b的类型不一样 ===用来进行严格的比较判断

在业务中使用了如下逻辑:访问某页面时需要登陆,如果未登陆则跳转至登陆页面,登陆后返回这个页面。

相关js如下:

1
2
3
4
5
if (!localStorage.userinfo) {
window.location.href = "login.html?lastpage=" + window.location.href;
} else {
xxx;
}

在login.html中有如下代码:

1
2
3
4
5
6
7
8
var lastpage;
var url = window.location.search;
var loc = url.substring(url.lastIndexOf('=') + 1, url.length);
if (loc == null || loc == "") {
lastpage = "usercenter.html"
} else {
lastpage = loc;
}

在登陆的ajax的callback success中有

1
window.location.href = lastpage;


然而,在实际的使用中出现了问题:在访问类似 http://xxx.com/product.html?id=1 时,发现最终跳转到的页面是 http://xxx.com/1,自然出现了 404 错误。后面发现是在 login.html?lastpage=http://xxx.com/product.html?id=1 的时候,程序直接将 1 看成了 lastpage。

有很多种方式可以解决问题,例如改进 login 中获取 url 参数的 js 等,但是我希望能够在之后也能使 url 不出现类似的错误,因此想到了对 url 进行转码。

1
window.location.href = "login.html?lastpage=" + encodeURIComponent(window.location.href);

可以将 http://xxx.com/product.html?id=1 转换成 http%3A%2F%2Fxxx.com%2Fproduct.html%3Fid%3D1

可是此时又会发现最终访问到的页面地址是 http://xxx.com/http%3A%2F%2Fxxx.com%2Fproduct.html%3Fid%3D1

看来是浏览器将已经转码的url当成一个文件访问了。因此,在 login 的 callback 里对其重新进行解码:

1
window.location.href = unescape(lastpage);

可以将转码过的url还原。

  1. 登陆root
  2. 更改httpd.conf
    1
    vi /etc/httpd/conf/http.conf
    使用vi进行修改。用到的快捷键: 跳到文件第一行:gg 跳到文件最后一行:shift + g
  3. 加入内容:
    1
    2
    3
    4
    5
    6
    7
    8
    <VirtualHost xxx.com>
    ServerAdmin root@localhost
    DocumentRoot /var/www/html/xxx
    ServerName xxx.com
    <Directory /var/www/html/xxxx>
    Require all granted
    </Directory>
    </VirtualHost>

重启apache

1
service httpd restart

然后即可设置xxx.com的域名解析到此服务器。 > 使用过程中发现设置xxx.com的虚拟目录后,xxx.com能够成功解析到服务器,然而www.xxx.com不能成功解析,重新操作了一般,又添加了一个www.xxx.com的虚拟目录后能够成功解析。

upload successful

如同人的神经元一般,由输入端-神经元-输出这样一系列过程的信息处理方式,可以处理较为复杂的信息,并有一定的学习功能。

神经网络一般分为:输入层、隐藏层、输出层。对于用户来说,只有输出层的输出是可知的,隐藏层可以完成许多间接的复杂运算,因此神经网络的计算复杂度比单层结构复杂的多。

upload successful

上图为一个有两层隐藏层的典型的神经网络,可以看到其基本结构.可以发现任何一个节点相当于收到上一层所有节点的影响.每个节点影响的程度可以以权值表示。

以下面一个简单的神经网络举例,

upload successful

隐藏层(a(2)1,a(2)2,a(2)3)的值的计算为:

\[a^{(2)}_1 = g(\theta ^{(1)}_{10}x_0 + \theta ^{(1)}_{11}x_1 + \theta ^{(1)}_{12}x_2 + \theta ^{(1)}_{13}x_3)\]

\[a^{(2)}_2 = g(\theta ^{(1)}_{20}x_0 + \theta ^{(1)}_{21}x_1 + \theta ^{(1)}_{22}x_2 + \theta ^{(1)}_{23}x_3)\]

\[a^{(2)}_3 = g(\theta ^{(1)}_{30}x_0 + \theta ^{(1)}_{31}x_1 + \theta ^{(1)}_{32}x_2 + \theta ^{(1)}_{33}x_3)\]

\(\theta\)即表示相应层元素受到上一层“激励”的权值。(x0为加上的额外的偏度单元)

g为S函数(解决逻辑回归问题)

同理,输出层的值为

\[h_\theta(x)=a^{(3)}_1 = g(\theta ^{(2)}_{10}a_0 + \theta ^{(2)}_{11}a_1 + \theta ^{(2)}_{12}a_2 + \theta ^{(2)}_{13}a_3)\]

为前一层(隐藏层)的所以元素乘对应的权值的和的对应函数值。


\[a^{(2)}_1 = g(\theta ^{(1)}_{10}x_0 + \theta ^{(1)}_{11}x_1 + \theta ^{(1)}_{12}x_2 + \theta ^{(1)}_{13}x_3)\]

\[a^{(2)}_2 = g(\theta ^{(1)}_{20}x_0 + \theta ^{(1)}_{21}x_1 + \theta ^{(1)}_{22}x_2 + \theta ^{(1)}_{23}x_3)\]

\[a^{(2)}_3 = g(\theta ^{(1)}_{30}x_0 + \theta ^{(1)}_{31}x_1 + \theta ^{(1)}_{32}x_2 + \theta ^{(1)}_{33}x_3)\]

对于以上式子可以看成矩阵相乘的形式,

\[x=\begin{bmatrix}x_0\ x_1\ x_2\ x_3\end{bmatrix}\]

\[z^{(2)}=\begin{bmatrix}z_1^{(2)}\ z_2^{(2)}\ z_3^{(2)}\end{bmatrix}\]

\[z^{(2)} = \theta^{(1)}x\]

\[a^{(2)}=g(z^{(2)})\]

z(2)为第二层元素值的向量形式。(1)为输入层对应的权值的向量形式。

\[z^{(3)} = \theta^{(2)}a^{(2)}\]

\[h_\theta(x)=a^{(3)}=g(z^{(3)})\]

(2)为隐藏层对应权值的向量形式。

神经网络中这种由训练输入送入网络中,获得激励响应的行为称为“前向传播”


神经网络解决实际问题

例如下表:

x1 x2 y
0 0 0
1 0 0
0 1 0
1 1 1

在神经网络中,可以以下形式表示

upload successful

计算一下,发现x1与x2等于0时z=-30,x1与x2等于1时z=10,x1与x2不相等时z=-10.

将其放到S函数中,

upload successful

z=-30与z=-10时g(z)趋近与0,z=10时趋近与1,可以表示上表的值的关系。

可以用y=x1 AND x2 (与)表示这个关系。


下表用神经网络表示:

x1 x2 y
0 0 1
1 0 0
0 1 0
1 1 1

这种“异或”问题可以看成一个“与”与一个“或”问题的结合,

upload successful

(NOT)

upload successful

(AND)

(NOT x1)AND(NOT x2)

upload successful

可以得到上表内容。

以上为神经网络表示“异或”运算。

必须要两层网络才能解决异或运算问题。因为1层网络放在坐标图上可以看成是画了一条直线,而异或问题放在图上是这样的:

upload successful

不难发现没有一条直线能够完美地分开两类点。

1
2
# -*- coding:utf-8 -*-  
#encoding:utf-8

为了使处理文件时用 utf-8 编码,做如上编码声明


1
2
3
4
5
import hashlib
def md5(text):
m = hashlib.md5()
m.update(text)
return m.hexdigest()

利用 hashlib 进行 md5 编码


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
def import_points_csv(filename,outfilename):
print(filename)
g=file(outfilename,&quot;w+&quot;)
#使用w+(写入模式)打开文件outfilename
with open(filename, 'r') as f:
#读取filename
line = f.readline()
#逐行读取f。因为要处理csv的列因此逐行处理
while line:
line = line.replace('n','')
line = line.replace('r','')
#处理每行的字符串,使其为单纯的一行以逗号分隔的文字
row = line.split(',')
#用逗号作为分隔符,对字符串line进行切片,以数组的形式存入row中
state = row[0].strip()
date = row[20]
thistype = '国控'
print(thistype)
name = row[1].strip()
stationid = md5(name+state+thistype)
row[21] = stationid
md5id = md5(date+stationid)
row[22] = md5id
row[1]
#对数组row进行处理。
print(row)
for i in range(0, len(row)-1):
row[i] = row[i] + ','
#对row进行拼接,分隔符为逗号
g.writelines(row)
g.writelines('n')
#逐行写入文件,每行的最后加上一个换行符。
line = f.readline()
g.close()
1
import_points_csv('国控2.csv'.decode('utf-8').encode('gbk'),'contry_2.csv')

由于文件名是中文,因此要将其编码才能被程序读取,不然在运行时显示文件名为乱码且无法读取