入门学期期间采用IDLE(Integrated Development and Learning Environment)编辑器学习!!
一
1、标识符
区分大小写、首字符可下划线(_)可字母,不可数字、关键字不能是标识符(if)、内置函数不能是标识符(print)
2、关键字
import keyword
print(keyword.kwlist)
# 输出结果['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
3、变量
python中不需要提前声明变量的数据类型,会自动推断出类型(字符串、浮点、整数)
python作为动态类型语言,变量接受再次定义(y=20之后依然可以定义y=True)
4、语句
一行语句一次编译,一条语句结束后,不加分号
5、注释
# (#后面加空格)
如果要在python2的py文件里面写中文,则必须要添加一行声明文件编码的注释,否则python2会默认使用ASCII编码
# coding=utf-8
# -*- coding:utf-8 -*-
6、模块
三种导入语句的方式:
import<模块名>
from<模块名>import<代码元素>
from<模块名>import<代码元素>as<代码元素别名>
# 例如m2模块为x=20
# 第一种
import m2
y=20
print(m2.x) # 导入特定代码元素要加前缀
# 第二种
from m2 import x
y=20
print(x)
# 第三种
from m2 import x as x2 # 由于这个代码段中已经有x了
x=100
y=20
print(x2)
7.数据类型
6种内置数据类型:数字、字符串、列表、元组、集合、字典(容器类型)
数字类型:①整数类型(int)
熟悉python中简单的进制转换
# n进制转十进制:int()函数,第一个参数是一个字符串,第二个参数是字符串的进制
a = '11100'
print(int(a,2)) # 结果为28
# n进制转十六进制,调用hex函数或format
print(hex(28)) # 输出0x1c,注:0x是十六进制的标志
print(format(28,"x")) # 输出1c
# n进制转八进制,调用oct函数
print(oct(28)) # 输出0o34,注:0o是八进制的标志
print(format(28,"o")) # 输出34
# n进制转二进制,调用bin函数
print(bin(28)) # 输出0b11100,注:0b是二进制的标志
print(format(28,"b")) # 输出11100
②浮点类型(float)、③复数类型(complex)
④布尔类型(True或False)
使用bool()内置函数会直接给出Ture或False的结果
print(bool(0)) # 输出False
print(bool(1)) # 输出Ture
8、数字类型相互转换
隐式转换(运算时)
a = 1.0 + 1
print(a) # 输出2.0,此过程中整数1转化为浮点数
显式转换
print(int(False)) # 输出0
print(float(False)) # 输出0.0
9、逻辑运算符
and or not
3 < 4 and 4 < 5
True
3 < 4 and 4 > 5
False
3 < 4 or 4 > 5
True
not 0
True
not 1
False
注意:短路逻辑&计算符优先级
短路逻辑:为什么?(not 1) or (0 and 1) or (3 and 4) or (5 and 6) or (7 and 8 and 9) = 4
即 False or 0 or 4 or 6 or 9 = 4
3 and 4
4
3 or 4
3
由于and左右两边均为Ture,结果才为Ture,即第二个操作数4影响了最后的结果
所以直接把4作为结果
同理,or左右有一个为Ture结果就为Ture,即第一个操作数3已经满足,后面第二个操作数4不影响结果
所以3为输出结果
0 and 3
0
0 or 3
3
总结:python显然没有把所有结果判断完才出结果,更高效的是直接把影响结果的关键值作为结果
计算符优先级:为什么?(not 1 or 0 and 1 or 3 and 4 or 5 and 6 or 7 and 8 and 9)=4
二
分支和循环
分支结构:if(五种)
①判断一个条件,如果这个条件成立,就执行其包含的某条语句或某个代码块
②判断一个条件,如果这个条件成立,就执行其包含的某条语句或某个代码块;
如果不成立(else),就执行另外的某条语句或某个代码块
③判断多个条件,如果第一个不成立,继续判断第二个,如果第二个变成了,继续判断第三个...
例如输入分数划分等级的代码
score = input("请输入分数")
score = int(score)
if 0<= score < 60:
print("D")
if 60<= score < 80:
print("C")
if 80<= score < 90:
print("B")
if 90<= score < 100:
print("A")
if score == 100:
print("S")
上述代码流程图为
score = input("请输入分数")
score = int(score)
if 0<= score < 60:
print("D")
elif 60<= score < 80:
print("C")
elif 80<= score < 90:
print("B")
elif 90<= score < 100:
print("A")
elif score == 100:
print("S")
上述代码流程图为
第二个elif的语句更聪明,不需要次次都判断多个条件!
④第四种是在③的情况下添加一个else,表示上面条件均不成立的情况下,执行某条语句或代码块
score = input("请输入分数")
score = int(score)
if 0<= score < 60:
print("D")
elif 60<= score < 80:
print("C")
elif 80<= score < 90:
print("B")
elif 90<= score < 100:
print("A")
elif score == 100:
print("S")
else:
print("请输入0-100之内的整数")
⑤条件结构:条件成立时执行的语句+if+条件+else+条件不成立时执行的语句
例如有如下代码段:
age=16
if age < 18:
print("禁止访问")
else:
print("欢迎访问")
改写为条件结构:
age = 16
print("禁止访问") if age < 18 else print("欢迎访问")
好处:缩减为一行,变成表达式之后,很容易打入一个语句的内部
又例如:
a = 3
b = 5
if a < b:
small = a
else:
small = b
print(small)
a = 3
b = 5
small = a if a < b else b
print(small)
又例如对④中的代码段改写
score = 87
level = ('D' if 0<= score < 60 else
'C' if 60<= score < 80 else
'B' if 80<= score < 90 else
'A' if 90<= score < 100 else
'S' if score == 100 else
"请输入0-100之内的整数" )
print(level)
分支的嵌套:
例如年龄+性别嵌套
age = 18
isMale = True
if age < 18:
print("拒绝访问")
else:
if isMale:
print("欢迎访问")
else:
print("因非Male拒绝访问")
循环结构(while\for):如果条件成立,循环会一直执行
break\continue语句:跳出循环,continue跳出本次循环,执行下一次;break强制退出循环
i = 0
while i < 10:
i += 1
if i % 2 == 0:
continue
print(i)
1
3
5
7
9
else语句:当循环条件不再为真的时候,便执行else语句的内容
while else语句容易检测出循环的退出状况
例如简单的打卡小程序:
day = 1
while day <= 7:
answer = input("七天打卡")
if answer != "1":
break
day += 1
else:
print("完成七天打卡")
循环结构的嵌套:
例如九九乘法表
i = 1
while i<= 9:
j = 1
while j <= i:
print(j, "*" , i , "=" , j * i , end="")
j += 1
print()
i += 1
for循环:" for 变量 in 可迭代对象: "
(可迭代对象指元素能单独被提取出的对象)
for a in "messi":
print(a)
m
e
s
s
i
用for循环写1+2+3+...+1000000的和:
sum = 0
for i in 1000000:
sum += i
报错:
for i in 1000000:
TypeError: 'int' object is not iterable
1000000作为一个整数,不是可迭代对象。为满足需求,引入range()函数:生成数字序列
①range(stop):生成一个从0开始到stop的整数数列
for i in range(11):
print(i)
0
1
2
3
4
5
6
7
8
9
10
②range(start,stop)
for i in range(5,11):
print(i)
5
6
7
8
9
10
③range(start,stop,step):多一个参数用来指定跨度
for i in range(5,11,2):
print(i)
5
7
9
用for循环写1+2+3+...+1000000的和:
sum = 0
for i in range(1000001):
sum += i
print(sum)
500000500000
找出10以内的所有质数:
for i in range(2,10):
for n in range(2,i):
if i % n == 0:
print(i, "=", n, "*", i // n)
break
else:
print(i, "是一个质数")
2 是一个质数
3 是一个质数
4 = 2 * 2
5 是一个质数
6 = 2 * 3
7 是一个质数
8 = 2 * 4
9 = 3 * 3
三
列表:[a,b,...]
第1个元素下标索引是0,第2个元素下标索引是1,······
n = [1, 2, 3, "messi"]
n[0]
1
n[1]
2
n[2]
3
n[3]
'messi'
若一个列表无限长,不知道最后一个元素,可通过len()函数获取列表长度
n = [1, 2, 3, 4, "messi"]
length = len(n)
n[length - 1]
'messi'
列表切片
n = [1, 2, 3, 4, "messi"]
n[:3]
[1, 2, 3]
n[3:]
[4, 'messi']
n[:3:2]
[1, 3]
#简单的倒序输出
n[::-1]
['messi', 4, 3, 2, 1]
列表的“增、删、改、查”
增:
①append():在末尾增加一个元素
n = [1, 2, 3, 4, "messi"]
n.append("neymar")
n
[1, 2, 3, 4, 'messi', 'neymar']
②extend():在末尾增加多个可迭代对象
n = [1, 2, 3, 4, "messi",'neymar']
n.extend(["kobe","curry"])
n
[1, 2, 3, 4, 'messi', 'neymar', 'kobe', 'curry']
③insert():在任意位置增加
n
[1, 2, 3, 4, 'messi', 'neymar', 'kobe', 'curry']
n.insert(5,"mbappe")
n
[1, 2, 3, 4, 'messi', 'mbappe', 'neymar', 'kobe', 'curry']
删:
①remove():删除指定元素
n
[1, 2, 3, 4, 'messi', 'mbappe', 'neymar', 'kobe', 'curry']
n.remove("mbappe")
n
[1, 2, 3, 4, 'messi', 'neymar', 'kobe', 'curry']
②pop():删除指定索引位置的元素
n
[1, 2, 3, 4, 'messi', 'neymar', 'kobe', 'curry']
n.pop(6)
'kobe'
n
[1, 2, 3, 4, 'messi', 'neymar', 'curry']
③clear():清空所有
n
[1, 2, 3, 4, 'messi', 'neymar', 'curry']
n.clear()
n
[]
改:
①替换
n = [1, 2, 3, 4, "messi","neymar"]
n[4] = "世界杯冠军"
n
[1, 2, 3, 4, '世界杯冠军', 'neymar']
n
[1, 2, 3, 4, '世界杯冠军', 'neymar']
n[4:] = ["冠军","亚军"]
n
[1, 2, 3, 4, '冠军', '亚军']
②排序:若列表中的元素都是数字,从小到大排序可调用sort()函数,从大到小排序可调用sort()之后再用reverse()
nums = [1, 8, 0, 4, 7, 2, 6, 4, 6, 2, 7]
nums.sort()
nums
[0, 1, 2, 2, 4, 4, 6, 6, 7, 7, 8]
nums.reverse()
nums
[8, 7, 7, 6, 6, 4, 4, 2, 2, 1, 0]
or
nums = [1, 8, 0, 4, 7, 2, 6, 4, 6, 2, 7]
nums.sort(reverse=True)
nums
[8, 7, 7, 6, 6, 4, 4, 2, 2, 1, 0]
查:
①count():查找列表里有多少个指定元素
nums = [1, 8, 0, 4, 7, 2, 6, 4, 6, 2, 7]
nums.count(2)
2
②index():查找对应元素的索引值
n = [1, 2, 3, 4, "messi","neymar"]
n.index("messi")
4
因此,面对很多列表元素时,想替换某一个,可以直接索引替换
n = [1, 2, 3, 4, "messi","neymar"]
n[n.index("messi")] = "世界杯冠军"
n
[1, 2, 3, 4, '世界杯冠军', 'neymar']
③浅拷贝
copy()
nums = [1, 8, 0, 4, 7, 2, 6, 4, 6, 2, 7]
nums_copy1 = nums.copy()
nums_copy1
[1, 8, 0, 4, 7, 2, 6, 4, 6, 2, 7]
或用切片方法
nums = [1, 8, 0, 4, 7, 2, 6, 4, 6, 2, 7]
nums_copy2 = nums[:]
nums_copy2
[1, 8, 0, 4, 7, 2, 6, 4, 6, 2, 7]
列表的加法和乘法:乘法是重复列表内元素若干次
s = [1, 2, 3]
t = [4, 5, 6]
s + t
[1, 2, 3, 4, 5, 6]
s * 3
[1, 2, 3, 1, 2, 3, 1, 2, 3]
嵌套列表:在列表里嵌入一个新列表,也叫二维列表
matrix = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
matrix
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
matrix矩阵
访问嵌套列表
例如将上述matrix矩阵中的元素一一访问:
for i in matrix:
for each in i:
print(each, end=' ')
print()
1 2 3
4 5 6
7 8 9
访问某个元素:
matrix[0][0]
1
matrix[1][1]
5
创建矩阵的另一种方法:先写一行,再循环
A = [0] * 3
A
[0, 0, 0]
for i in range(3):
A[i] = [0] * 3
A
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
嵌套列表浅拷贝时会发生错误,例如:
x = [[1, 2, 3],[4, 5, 6],[7, 8, 9]]
y = x[:]
x[1][1] = 0
x
[[1, 2, 3], [4, 0, 6], [7, 8, 9]]
y
[[1, 2, 3], [4, 0, 6], [7, 8, 9]]
因此需要引入深拷贝,用到copy模块中的deepcopy函数:
import copy
x = [[1, 2, 3],[4, 5, 6],[7, 8, 9]]
y = copy.deepcopy(x)
x[1][1] = 0
x
[[1, 2, 3], [4, 0, 6], [7, 8, 9]]
y
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
deepcopy不仅对原对象进行拷贝,还将对象中引用的子对象也拷贝
列表推导式:[expression for target in iterable] ,for循环将返回值赋给target,再进行expression运算
n = [i + 1 for i in range(10)]
n
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
用列表推导式往往可以代替循环,上面学过创建二维列表要用循环写,如:
A = [0] * 3
A
[0, 0, 0]
for i in range(3):
A[i] = [0] * 3
A
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
A[1][1] = 1
A
[[0, 0, 0], [0, 1, 0], [0, 0, 0]]
用列表推导式:
B = [[0] * 3 for i in range(3)]
B
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
B[1][1] = 1
B
[[0, 0, 0], [0, 1, 0], [0, 0, 0]]
列表推导式还可以筛选:[expression for target in iterable if 条件]
例如筛选0~10偶数
n = [i for i in range(10) if i % 2 == 0]
n
[0, 2, 4, 6, 8]
例如筛选字符串中的M开头的字母
words = ["Messi", "Mbappe", "Neymar"]
A = [i for i in words if i[0] == "M"] #字符串肯定索引值啊!!!
A
['Messi', 'Mbappe']
列表推导式实现嵌套
①二位列表降阶为一维列表
matrix = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
n = [i for j in matrix for i in j]
n
[1, 2, 3, 4, 5, 6, 7, 8, 9]
用for循环翻译过来即:
n = [] #把n重新取为空列表
for j in matrix:
for i in j:
n.append(i)
n
[1, 2, 3, 4, 5, 6, 7, 8, 9]
②列表推导式写九九乘法表
result = [str(j) + ' * ' + str(i) + ' = ' + str(i * j) for i in range(1,10) for j in range(1,10) if i >= j] #注意字符串“+”连接
机器学习阶段pycharm学习
1.1 BMI
# -*- coding: utf-8 -*-
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
from sklearn import datasets
import matplotlib.pyplot as plt
from sklearn import linear_model
import numpy as np
#数据集划分
diabetes = datasets.load_diabetes() #载入数据
diabetes_x_temp = diabetes.data[:, np.newaxis, 2] #获取其中一个特征
diabetes_x_train = diabetes_x_temp[:-20] #训练样本
diabetes_x_test = diabetes_x_temp[-20:] #测试样本 后20行
diabetes_y_train = diabetes.target[:-20] #训练标记
diabetes_y_test = diabetes.target[-20:] #预测对比标记
#回归训练及预测
clf = linear_model.LinearRegression()
clf.fit(diabetes_x_train, diabetes_y_train) #训练数据集
pre = clf.predict(diabetes_x_test)
#绘图
plt.title(u'LinearRegression Diabetes体质指数BMI') #标题 注:解决plt.title()输出中文,加上最上面两行的内容即可!
plt.xlabel(u'Attributes') #x轴坐标
plt.ylabel(u'Measure of disease') #y轴坐标
plt.scatter(diabetes_x_test, diabetes_y_test, color = 'black') #散点图
plt.plot(diabetes_x_test, pre, color='blue', linewidth = 2) #预测直线
plt.show()
代码分析:
①代码段
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
负责解决plt.title()中文输出问题
②数据来源为庞大的sklearn库中的datasets数据集中的diabetes糖尿病数据
③需要绘图,引入matplotlib
④获取训练集特征的时候用到np.newaxis:
np.newaxis 的功能是增加新的维度,
- x[:, np.newaxis] ,列上增加维度
- x[np.newaxis, :] ,行上增加维度
用途:通常用它将一维的数据转换成一个矩阵,这样就可以与其他矩阵进行相乘
1.2 ABP
# -*- coding: utf-8 -*-
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
from sklearn import datasets
import matplotlib.pyplot as plt
from sklearn import linear_model
import numpy as np
#数据集划分
diabetes = datasets.load_diabetes() #载入数据
diabetes_x_temp = diabetes.data[:, np.newaxis, 3] #获取其中一个特征
diabetes_x_train = diabetes_x_temp[:-20] #训练样本
diabetes_x_test = diabetes_x_temp[-20:] #测试样本 后20行
diabetes_y_train = diabetes.target[:-20] #训练标记
diabetes_y_test = diabetes.target[-20:] #预测对比标记
#回归训练及预测
clf = linear_model.LinearRegression()
clf.fit(diabetes_x_train, diabetes_y_train) #训练数据集
pre = clf.predict(diabetes_x_test)
#绘图
plt.title(u'LinearRegression Diabetes平均血压ABP') #标题
plt.xlabel(u'Attributes') #x轴坐标
plt.ylabel(u'Measure of disease') #y轴坐标
plt.scatter(diabetes_x_test, diabetes_y_test, color = 'black') #散点图
plt.plot(diabetes_x_test, pre, color='blue', linewidth = 2) #预测直线
plt.show()
1.3 工龄和薪水
# 导入设置
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
# 设置显示中文
plt.rcParams['font.sans-serif'] = ['KaiTi']
plt.rcParams['axes.unicode_minus'] = False
#读取数据
df = pd.read_excel('E://go/IT行业收入表.xlsx')
df.head(10)
X = df[['工龄']] #这里的自变量必须写成二维形式,一个因变量可能对应多个自变量
Y = df['薪水']
# 模型搭建
model = LinearRegression()
model.fit(X,Y)
# 模型可视化
plt.scatter(X,Y)
plt.plot(X, model.predict(X), color='red')
plt.xlabel('工龄')
plt.ylabel('薪水')
plt.show()
#查看系数,截距:线性回归方程构造
model.coef_,model.intercept_
代码分析:
①Pandas中的head函数:df.head(n):该方法用于查看dataframe数据表中开头n行的数据,若参数n未设置,即df.head(),则默认查看dataframe中前5行的数据。
# 读入图片
import cv2 #opencv读取的格式是BGR
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
img=cv2.imread('E:/go/p1.png')
cv2.imshow("img",img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 灰度图显示
img=cv2.imread('E:/go/p1.png',cv2.IMREAD_GRAYSCALE)
代码解析:
①waitKey(0)为无限时间的显示函数,如果改为参数1就是显示1ms以此类推;destroyAllWindows()按下任意键便可关闭窗口
②关于图片是BGR格式的问题:深度学习中为什么普遍使用BGR而不用RGB?
因为caffe,作为最早最流行的一批库的代表,用了opencv,而opencv默认通道是bgr的。这是opencv的入门大坑之一,bgr是个历史遗留问题,为了兼容早年的某些硬件。
1.4 逻辑回归经典iris
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import numpy as np
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
#载入数据集
iris = load_iris()
X = X = iris.data[:, :2] #获取花卉两列数据集
Y = iris.target
#逻辑回归模型
lr = LogisticRegression(C=1e5)
lr.fit(X,Y)
#meshgrid函数生成两个网格矩阵
h = .02
x_min, x_max = X[:, 0].min() - .5, X[:, 0].max() + .5
y_min, y_max = X[:, 1].min() - .5, X[:, 1].max() + .5
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
#pcolormesh函数将xx,yy两个网格矩阵和对应的预测结果Z绘制在图片上
Z = lr.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.figure(1, figsize=(8,6))
plt.pcolormesh(xx, yy, Z, cmap=plt.cm.Paired)
#绘制散点图
plt.scatter(X[:50,0], X[:50,1], color='red',marker='o', label='setosa鸢尾花')
plt.scatter(X[50:100,0], X[50:100,1], color='blue', marker='x', label='versicolor鸢尾花')
plt.scatter(X[100:,0], X[100:,1], color='green', marker='s', label='Virginica鸢尾花')
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
plt.xticks(())
plt.yticks(())
plt.legend(loc=2)
plt.show()
1.5 分类算法breast_cancer
## 导入库
import pandas as pd
## 导入数据
dataset = pd.read_csv('E://go/github/Logistic-Regression/breast_cancer.csv')
X = dataset.iloc[:, 1:-1].values #取列数,X选取第二列至倒数第二列的特征量,即细胞的各项参数作为训练集
y = dataset.iloc[:, -1].values #Y选取最后一列的特征量,即分类作为测试集
## 将数据集分割成训练集和测试集
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
## 在训练集上训练逻辑回归模型
from sklearn.linear_model import LogisticRegression
classifier = LogisticRegression(random_state=0)
classifier.fit(X_train, y_train)
## 预测测试集结果
y_pred = classifier.predict(X_test)
## 创建混淆矩阵
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_test, y_pred)
print(cm)
结果: [[84 3] [ 3 47]]
1.6 测试神经元输入输出
import numpy as np
def sigmoid(x):
# 激活函数: f(x) = 1 / (1 + e^(-x))
return 1 / (1 + np.exp(-x))
class Neuron:
def __init__(self, weights, bias):
self.weights = weights
self.bias = bias
def feedforward(self, inputs):
# 加权输入,加入偏置,然后使用激活函数
total = np.dot(self.weights, inputs) + self.bias
return sigmoid(total)
weights = np.array([0, 1]) # w1 = 0, w2 = 1
bias = 1 # b = 1
n = Neuron(weights, bias)
x = np.array([2, 3]) # x1 = 2, x2 = 3
print(n.feedforward(x))
class OurNeuralNetwork:
'''
A neural network with:
- 2 inputs
- a hidden layer with 2 neurons (h1, h2)
- an output layer with 1 neuron (o1)
Each neuron has the same weights and bias:
- w = [0, 1]
- b = 0
'''
def __init__(self):
weights = np.array([0, 1])
bias = 0
# 这里是来自前一节的神经元类
self.h1 = Neuron(weights, bias)
self.h2 = Neuron(weights, bias)
self.o1 = Neuron(weights, bias)
def feedforward(self, x):
out_h1 = self.h1.feedforward(x)
out_h2 = self.h2.feedforward(x)
# o1的输入是h1和h2的输出
out_o1 = self.o1.feedforward(np.array([out_h1, out_h2]))
return out_o1
network = OurNeuralNetwork()
x = np.array([2, 3])
print(network.feedforward(x))
1.7 bp神经网络案例集合
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
from __future__ import division
import math
import random
import string
import pickle
flowerLables = {0:'Iris-setosa',
1:'Iris-versicolor',
2:'Iris-virginica'}
random.seed(0)
# 生成区间[a, b)内的随机数
def rand(a, b):
return (b-a)*random.random() + a
# 生成大小 I*J 的矩阵,默认零矩阵 (当然,亦可用 NumPy 提速)
def makeMatrix(I, J, fill=0.0):
m = []
for i in range(I):
m.append([fill]*J)
return m
# 函数 sigmoid,这里采用 tanh,因为看起来要比标准的 1/(1+e^-x) 漂亮些
def sigmoid(x):
return math.tanh(x)
# 函数 sigmoid 的派生函数, 为了得到输出 (即:y)
def dsigmoid(y):
return 1.0 - y**2
class NN:
''' 三层反向传播神经网络 '''
def __init__(self, ni, nh, no):
# 输入层、隐藏层、输出层的节点(数)
self.ni = ni + 1 # 增加一个偏差节点
self.nh = nh
self.no = no
# 激活神经网络的所有节点(向量)
self.ai = [1.0]*self.ni
self.ah = [1.0]*self.nh
self.ao = [1.0]*self.no
# 建立权重(矩阵)
self.wi = makeMatrix(self.ni, self.nh)
self.wo = makeMatrix(self.nh, self.no)
# 设为随机值
for i in range(self.ni):
for j in range(self.nh):
self.wi[i][j] = rand(-0.2, 0.2)
for j in range(self.nh):
for k in range(self.no):
self.wo[j][k] = rand(-2.0, 2.0)
# 最后建立动量因子(矩阵)
self.ci = makeMatrix(self.ni, self.nh)
self.co = makeMatrix(self.nh, self.no)
def update(self, inputs):
if len(inputs) != self.ni-1:
raise ValueError('与输入层节点数不符!')
# 激活输入层
for i in range(self.ni-1):
#self.ai[i] = sigmoid(inputs[i])
self.ai[i] = inputs[i]
# 激活隐藏层
for j in range(self.nh):
sum = 0.0
for i in range(self.ni):
sum = sum + self.ai[i] * self.wi[i][j]
self.ah[j] = sigmoid(sum)
# 激活输出层
for k in range(self.no):
sum = 0.0
for j in range(self.nh):
sum = sum + self.ah[j] * self.wo[j][k]
self.ao[k] = sigmoid(sum)
# print self.ao
return self.ao[:]
def backPropagate(self, targets, N, M):
''' 反向传播 '''
# if len(targets) != self.no:
# raise ValueError('与输出层节点数不符!')
# 计算输出层的误差
output_deltas = [0.0] * self.no
for k in range(self.no):
error = targets[k]-self.ao[k]
output_deltas[k] = dsigmoid(self.ao[k]) * error
# 计算隐藏层的误差
hidden_deltas = [0.0] * self.nh
for j in range(self.nh):
error = 0.0
for k in range(self.no):
error = error + output_deltas[k]*self.wo[j][k]
hidden_deltas[j] = dsigmoid(self.ah[j]) * error
# 更新输出层权重
for j in range(self.nh):
for k in range(self.no):
change = output_deltas[k]*self.ah[j]
self.wo[j][k] = self.wo[j][k] + N*change + M*self.co[j][k]
self.co[j][k] = change
#print(N*change, M*self.co[j][k])
# 更新输入层权重
for i in range(self.ni):
for j in range(self.nh):
change = hidden_deltas[j]*self.ai[i]
self.wi[i][j] = self.wi[i][j] + N*change + M*self.ci[i][j]
self.ci[i][j] = change
# 计算误差
error = 0.0
# for k in range(len(targets)):
# error = error + 0.5*(targets[k]-self.ao[k])**2
error += 0.5*(targets[k]-self.ao[k])**2
return error
def test(self, patterns):
count = 0
for p in patterns:
target = flowerLables[(p[1].index(1))]
result = self.update(p[0])
index = result.index(max(result))
print(p[0], ':', target, '->', flowerLables[index])
count += (target == flowerLables[index])
# result_str = flowerLables[index]
# if target == result_str:
# count += 1
# else:
# pass
accuracy = float(count/len(patterns))
print('accuracy: %-.9f' % accuracy)
def weights(self):
print('输入层权重:')
for i in range(self.ni):
print(self.wi[i])
print()
print('输出层权重:')
for j in range(self.nh):
print(self.wo[j])
def train(self, patterns, iterations=1000, N=0.1, M=0.01):
# N: 学习速率(learning rate)
# M: 动量因子(momentum factor)
for i in range(iterations):
error = 0.0
for p in patterns:
inputs = p[0]
targets = p[1]
self.update(inputs)
error = error + self.backPropagate(targets, N, M)
if i % 100 == 0:
print('误差 %-.9f' % error)
def demo():
# 一个演示:教神经网络学习逻辑异或(XOR)------------可以换成你自己的数据试试
pat = [
[[0,0], [0]],
[[0,1], [1]],
[[1,0], [1]],
[[1,1], [0]]
]
# 创建一个神经网络:输入层有两个节点、隐藏层有两个节点、输出层有一个节点
n = NN(2, 2, 1)
# 用一些模式训练它
n.train(pat)
# 测试训练的成果(不要吃惊哦)
n.test(pat)
# 看看训练好的权重(当然可以考虑把训练好的权重持久化)
#n.weights()
import numpy as np
import pandas as pd
# features 0-3
# labels 4
def iris():
data = []
# read dataset
raw = pd.read_csv('E:/go/github/classification-master/iris.csv')
raw_data = raw.values
raw_feature = raw_data[0:,0:4]
for i in range(len(raw_feature)):
ele = []
ele.append(list(raw_feature[i]))
if raw_data[i][4] == 'Iris-setosa':
ele.append([1,0,0])
elif raw_data[i][4] == 'Iris-versicolor':
ele.append([0,1,0])
else:
ele.append([0,0,1])
data.append(ele)
# print data
# 随机排列data
random.shuffle(data)
# print data
training = data[0:100]
test = data[101:]
# print np.shape(l)
# print np.shape(data)
# training_set = np.c_[data, l]
nn = NN(4,7,3)
nn.train(training,iterations=10000)
# save weights
with open('wi.txt', 'w') as wif:
pickle.dump(nn.wi, wif)
with open('wo.txt', 'w') as wof:
pickle.dump(nn.wo, wof)
nn.test(test)
if __name__ == '__main__':
iris()
代码解析:
①激活函数tanh():简而言之,在iris作为数据来源的这段代码上,设置tanh作为激活函数能把变化敏感,之前S函数训练预测会造成误差的样本值掰回来
sigmoid在输入处于[-1,1]之间时,函数值变化敏感,一旦接近或者超出区间就失去敏感性,处于饱和状态,影响神经网络预测的精度值;
tanh的变化敏感区间较宽,导数值渐进于0、1,符合人脑神经饱和的规律,比sigmoid函数延迟了饱和期;
tanh在原点附近与y=x函数形式相近,当激活值较低时,可以直接进行矩阵运算,训练相对容易;
tanh和sigmoid都是全部激活(fire),使得神经网络较重(heavy)。
②归一化初始数据(训练前!)
训练前,为避免各个输入变量的数量级差异过大,影响求解算法的效果,一般会先将数据归一化到[-1,1]的区间
神经网络为什么要归一化?