Loading

2.2-2.6数据预处理、线性代数、微积分、自动微分、概率

2.2-2.6
数据预处理、线性代数、微积分、自动微分、概率

2.2.1读取数据集

import os

os.makedirs(os.path.join('..', 'data'), exist_ok=True)
data_file = os.path.join('..', 'data', 'house_tiny.csv')
with open(data_file, 'w') as f:
    f.write('NumRooms,Alley,Price\n')  # 列名
    f.write('NA,Pave,127500\n')
    f.write('2,NA,106000\n')
    f.write('4,NA,178100\n')
    f.write('NA,NA,140000\n')

import pandas as pd

data = pd.read_csv(data_file)
print(data)

"""
   NumRooms Alley   Price
0       NaN  Pave  127500
1       2.0   NaN  106000
2       4.0   NaN  178100
3       NaN   NaN  140000
"""

2.2.2处理缺失值

inputs, outputs = data.iloc[:, 0:2], data.iloc[:, 2]
inputs = inputs.fillna(inputs.mean(numeric_only=True))
print(inputs)

"""
   NumRooms Alley
0       3.0  Pave
1       2.0   NaN
2       4.0   NaN
3       3.0   NaN
"""

inputs = pd.get_dummies(inputs, dummy_na=True)
print(inputs)
"""
   NumRooms  Alley_Pave  Alley_nan
0       3.0           1          0
1       2.0           0          1
2       4.0           0          1
3       3.0           0          1
"""

2.2.3转换为张量格式

import tensorflow as tf

X, y = tf.constant(inputs.values), tf.constant(outputs.values)
X, y

"""
(<tf.Tensor: shape=(4, 3), dtype=float64, numpy=
 array([[3., 1., 0.],
        [2., 0., 1.],
        [4., 0., 1.],
        [3., 0., 1.]])>,
 <tf.Tensor: shape=(4,), dtype=int64, numpy=array([127500, 106000, 178100, 140000], dtype=int64)>)
"""

2.3.1标量

import tensorflow as tf

x = tf.constant(3.0)
y = tf.constant(2.0)

x+y, x*y, x/y, x**y

"""
(<tf.Tensor: shape=(), dtype=float32, numpy=5.0>,
 <tf.Tensor: shape=(), dtype=float32, numpy=6.0>,
 <tf.Tensor: shape=(), dtype=float32, numpy=1.5>,
 <tf.Tensor: shape=(), dtype=float32, numpy=9.0>)
"""

2.3.2向量

x = tf.range(4)
x

"""
<tf.Tensor: shape=(4,), dtype=int32, numpy=array([0, 1, 2, 3])>
"""

x[3]

"""
<tf.Tensor: shape=(), dtype=int32, numpy=3>
"""

len(x)

"""
4
"""

x.shape

"""
TensorShape([4])
"""

2.3.3矩阵

A = tf.reshape(tf.range(20), (5, -1))
A

"""
<tf.Tensor: shape=(5, 4), dtype=int32, numpy=
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15],
       [16, 17, 18, 19]])>
"""

tf.transpose(A)

"""
<tf.Tensor: shape=(4, 5), dtype=int32, numpy=
array([[ 0,  4,  8, 12, 16],
       [ 1,  5,  9, 13, 17],
       [ 2,  6, 10, 14, 18],
       [ 3,  7, 11, 15, 19]])>
"""

B = tf.constant([[1, 2, 3], [2, 0, 4], [3, 4, 5]])
B

"""
<tf.Tensor: shape=(3, 3), dtype=int32, numpy=
array([[1, 2, 3],
       [2, 0, 4],
       [3, 4, 5]])>
"""

B == tf.transpose(B)

"""
<tf.Tensor: shape=(3, 3), dtype=bool, numpy=
array([[ True,  True,  True],
       [ True,  True,  True],
       [ True,  True,  True]])>
"""

2.3.4张量

X = tf.reshape(tf.range(24), (2, 3, 4))
X

"""
<tf.Tensor: shape=(2, 3, 4), dtype=int32, numpy=
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]],

       [[12, 13, 14, 15],
        [16, 17, 18, 19],
        [20, 21, 22, 23]]])>
"""

2.3.5张量算法的基本性质

A = tf.reshape(tf.range(20, dtype=tf.float32), (5, 4))
B = A  # 不能通过分配新内存将A克隆到B
A, A+B

"""
(<tf.Tensor: shape=(5, 4), dtype=float32, numpy=
 array([[ 0.,  1.,  2.,  3.],
        [ 4.,  5.,  6.,  7.],
        [ 8.,  9., 10., 11.],
        [12., 13., 14., 15.],
        [16., 17., 18., 19.]], dtype=float32)>,
 <tf.Tensor: shape=(5, 4), dtype=float32, numpy=
 array([[ 0.,  2.,  4.,  6.],
        [ 8., 10., 12., 14.],
        [16., 18., 20., 22.],
        [24., 26., 28., 30.],
        [32., 34., 36., 38.]], dtype=float32)>)
"""

id(A), id(B)

"""
(1351416459856, 1351416459856)
"""

A * B

"""
<tf.Tensor: shape=(5, 4), dtype=float32, numpy=
array([[  0.,   1.,   4.,   9.],
       [ 16.,  25.,  36.,  49.],
       [ 64.,  81., 100., 121.],
       [144., 169., 196., 225.],
       [256., 289., 324., 361.]], dtype=float32)>
"""

a = 2
X = tf.reshape(tf.range(24), (2, 3, 4))
a + X, (a * X).shape

"""
(<tf.Tensor: shape=(2, 3, 4), dtype=int32, numpy=
 array([[[ 2,  3,  4,  5],
         [ 6,  7,  8,  9],
         [10, 11, 12, 13]],
 
        [[14, 15, 16, 17],
         [18, 19, 20, 21],
         [22, 23, 24, 25]]])>,
 TensorShape([2, 3, 4]))
"""

2.3.6降维

x = tf.range(4, dtype=tf.float32)
x, tf.reduce_sum(x)

"""
(<tf.Tensor: shape=(4,), dtype=float32, numpy=array([0., 1., 2., 3.], dtype=float32)>,
 <tf.Tensor: shape=(), dtype=float32, numpy=6.0>)
"""

A.shape, tf.reduce_sum(A)

"""
(TensorShape([5, 4]), <tf.Tensor: shape=(), dtype=float32, numpy=190.0>)
"""

A_sum_axis0 = tf.reduce_sum(A, axis=0)
A_sum_axis0, A_sum_axis0.shape

"""
(<tf.Tensor: shape=(4,), dtype=float32, numpy=array([40., 45., 50., 55.], dtype=float32)>,
 TensorShape([4]))
"""

A_sum_axis1 = tf.reduce_sum(A, axis=1)
A_sum_axis1, A_sum_axis1.shape

"""
(<tf.Tensor: shape=(5,), dtype=float32, numpy=array([ 6., 22., 38., 54., 70.], dtype=float32)>,
 TensorShape([5]))
"""

tf.reduce_sum(A, axis=[0, 1])

"""
<tf.Tensor: shape=(), dtype=float32, numpy=190.0>
"""

tf.reduce_mean(A), tf.reduce_sum(A) / tf.size(A).numpy()

"""
(<tf.Tensor: shape=(), dtype=float32, numpy=9.5>,
 <tf.Tensor: shape=(), dtype=float32, numpy=9.5>)
"""

tf.size(A)

"""
<tf.Tensor: shape=(), dtype=int32, numpy=20>
"""

tf.reduce_mean(A, axis=0), tf.reduce_sum(A, axis=0) / A.shape[0]

"""
(<tf.Tensor: shape=(4,), dtype=float32, numpy=array([ 8.,  9., 10., 11.], dtype=float32)>,
 <tf.Tensor: shape=(4,), dtype=float32, numpy=array([ 8.,  9., 10., 11.], dtype=float32)>)
"""

sum_A = tf.reduce_sum(A, axis=1, keepdims=True)
sum_A

"""
<tf.Tensor: shape=(5, 1), dtype=float32, numpy=
array([[ 6.],
       [22.],
       [38.],
       [54.],
       [70.]], dtype=float32)>
"""

A / sum_A

"""
<tf.Tensor: shape=(5, 4), dtype=float32, numpy=
array([[0.        , 0.16666667, 0.33333334, 0.5       ],
       [0.18181819, 0.22727273, 0.27272728, 0.3181818 ],
       [0.21052632, 0.23684211, 0.2631579 , 0.28947368],
       [0.22222222, 0.24074075, 0.25925925, 0.2777778 ],
       [0.22857143, 0.24285714, 0.25714287, 0.27142859]], dtype=float32)>
"""

tf.cumsum(A, axis=0)

"""
<tf.Tensor: shape=(5, 4), dtype=float32, numpy=
array([[ 0.,  1.,  2.,  3.],
       [ 4.,  6.,  8., 10.],
       [12., 15., 18., 21.],
       [24., 28., 32., 36.],
       [40., 45., 50., 55.]], dtype=float32)>
"""

2.3.7点积

y = tf.ones(4, dtype=tf.float32)
x, y, tf.tensordot(x, y, axes=1)

"""
(<tf.Tensor: shape=(4,), dtype=float32, numpy=array([0., 1., 2., 3.], dtype=float32)>,
 <tf.Tensor: shape=(4,), dtype=float32, numpy=array([1., 1., 1., 1.], dtype=float32)>,
 <tf.Tensor: shape=(), dtype=float32, numpy=6.0>)
"""

# 这里axes=1,说明取a的后1维即[3]和b的前1维即[3]进行矩阵相乘,其他维不变,那么根据矩阵乘法,自然得到c的大小为[2,3,2,6]
a = tf.ones(shape=(2, 3, 3))
b = tf.ones(shape=(3, 2, 6))
print(tf.tensordot(a, b, axes=1).shape)

"""
(2, 3, 2, 6)
"""

# 这里c的大小为[2,6],axes=2,即取a的后两维相乘后得到的2*3=6,与b的前两维相乘后得到的3*2=6,进行矩阵相乘运算,
# 即大小为[2,6]的矩阵与大小为[6,6]的矩阵进行矩阵相乘运算,得到的c的大小即为[2,6]
a = tf.ones(shape=(2, 2, 3))
b = tf.ones(shape=(3, 2, 6))
print(tf.tensordot(a, b, axes=2).shape)

"""
(2, 6)
"""

# 如果axes参数是一个元组,则元组的第一维指第一个乘数a要做运算的下标,第二维指第二个乘数要做运算的下标。
# 这里axes=(1,1),也就是说a的第1维与b的第一维进行矩阵相乘。相当于[2,3,2]*[2,3,6],结果c即为[2,3,3,6]
a = tf.ones(shape=(2, 2, 3))
b = tf.ones(shape=(3, 2, 6))
print(tf.tensordot(a, b, axes=(1, 1)).shape)

"""
(2, 3, 3, 6)
"""

# axes同样是元组,这里表明a的第1,2维和b的第0,1维进行矩阵乘法。即[2,2*3] * [3*2,6]= [2,6] * [6,6] = [2,6],c的大小即为[2,6]
a = tf.ones(shape=(2, 2, 3))
b = tf.ones(shape=(3, 2, 6))
print(tf.tensordot(a, b, axes=((1, 2), (0, 1))).shape)

"""
(2, 6)
"""

tf.reduce_sum(x * y)

"""
<tf.Tensor: shape=(), dtype=float32, numpy=6.0>
"""

2.3.8矩阵-向量积

A.shape, x.shape, tf.linalg.matvec(A, x)

"""
(TensorShape([5, 4]),
 TensorShape([4]),
 <tf.Tensor: shape=(5,), dtype=float32, numpy=array([ 14.,  38.,  62.,  86., 110.], dtype=float32)>)
"""

2.3.9矩阵-矩阵乘法

B = tf.ones((4, 3), tf.float32)
tf.matmul(A, B)

"""
<tf.Tensor: shape=(5, 3), dtype=float32, numpy=
array([[ 6.,  6.,  6.],
       [22., 22., 22.],
       [38., 38., 38.],
       [54., 54., 54.],
       [70., 70., 70.]], dtype=float32)>
"""

2.3.10范数

u = tf.constant([-3.0, -4.0])
tf.norm(u)

"""
<tf.Tensor: shape=(), dtype=float32, numpy=5.0>
"""

tf.reduce_sum(tf.abs(u))

"""
<tf.Tensor: shape=(), dtype=float32, numpy=7.0>
"""

tf.norm(tf.ones((4, 9)))

"""
<tf.Tensor: shape=(), dtype=float32, numpy=6.0>
"""

2.4.1导数和微分

import numpy as np
from matplotlib_inline import backend_inline
import matplotlib.pyplot as plt

def f(x):
    return 3 * x ** 2 - 4 * x

def numeric_lim(f, x, h):
    return (f(x+h) - f(x)) / h

h = 0.1
for i in range(5):
    print(f'h={h:.5f}, numerical limit={numeric_lim(f, 1, h):.5f}')
    h *= 0.1

"""
h=0.10000, numerical limit=2.30000
h=0.01000, numerical limit=2.03000
h=0.00100, numerical limit=2.00300
h=0.00010, numerical limit=2.00030
h=0.00001, numerical limit=2.00003
"""

def use_svg_display():
    backend_inline.set_matplotlib_formats('svg')

def set_figsize(figsize=(3.5, 2.5)):
    use_svg_display()
    plt.rcParams['figure.figsize'] = figsize

def set_axes(axes, xlabel, ylabel, xlim, ylim, xscale, yscale, legend):
    """设置matplotlib的轴"""
    axes.set_xlabel(xlabel)
    axes.set_ylabel(ylabel)
    axes.set_xscale(xscale)
    axes.set_yscale(yscale)
    axes.set_xlim(xlim)
    axes.set_ylim(ylim)
    if legend:
        axes.legend(legend)
    axes.grid()

def plot(X, Y=None, xlabel=None, ylabel=None, legend=None, xlim=None,
         ylim=None, xscale='linear', yscale='linear',
         fmts=('-', 'm--', 'g-.', 'r:'), figsize=(3.5, 2.5), axes=None):
    """绘制数据点"""
    if legend is None:
        legend = []

    set_figsize(figsize)
    axes = axes if axes else plt.gca()

    # 如果X有一个轴,输出True
    def has_one_axis(X):
        return (hasattr(X, "ndim") and X.ndim == 1 or isinstance(X, list)
                and not hasattr(X[0], "__len__"))

    if has_one_axis(X):
        X = [X]
    if Y is None:
        X, Y = [[]] * len(X), X
    elif has_one_axis(Y):
        Y = [Y]
    if len(X) != len(Y):
        X = X * len(Y)
    axes.cla()
    for x, y, fmt in zip(X, Y, fmts):
        if len(x):
            axes.plot(x, y, fmt)
        else:
            axes.plot(y, fmt)
    set_axes(axes, xlabel, ylabel, xlim, ylim, xscale, yscale, legend)

x = np.arange(0, 3, 0.1)
plot(x, [f(x), 2*x-3], 'x', 'f(x)', legend=['f(x)', 'Tangent line (x=1)'])  

2.5.1自动微分简单示例

import tensorflow as tf

x = tf.range(4, dtype=tf.float32)
x

"""
<tf.Tensor: shape=(4,), dtype=float32, numpy=array([0., 1., 2., 3.], dtype=float32)>
"""

x = tf.Variable(x)

# 把所有计算记录在磁带上
with tf.GradientTape() as t:
    y = 2 * tf.tensordot(x, x, axes=1)
y

"""
<tf.Tensor: shape=(), dtype=float32, numpy=28.0>
"""

x_grad = t.gradient(y, x)
x_grad

"""
<tf.Tensor: shape=(4,), dtype=float32, numpy=array([ 0.,  4.,  8., 12.], dtype=float32)>
"""

x_grad == 4 * x

"""
<tf.Tensor: shape=(4,), dtype=bool, numpy=array([ True,  True,  True,  True])>
"""

with tf.GradientTape() as t:
    y = tf.reduce_sum(x)
t.gradient(y, x)  # 被新计算的梯度覆盖

"""
<tf.Tensor: shape=(4,), dtype=float32, numpy=array([1., 1., 1., 1.], dtype=float32)>
"""

2.5.2非标量变量的反向传播

with tf.GradientTape() as t:
    y = x * x
t.gradient(y, x)

"""
<tf.Tensor: shape=(4,), dtype=float32, numpy=array([0., 2., 4., 6.], dtype=float32)>
"""

2.5.3分离计算

# 设置persistent=True来运行t.gradient多次
# 在调用gradient的时候,tf.GradientTape()的内容会被立即释放,如果要计算多组微分,则需要添加参数persistent=True
# 如果是常量的话需要添加watch来监控
with tf.GradientTape(persistent=True) as t:
    y = x * x
    u = tf.stop_gradient(y)
    z = u * x
x_grad = t.gradient(z, x)
x_grad == u

"""
<tf.Tensor: shape=(4,), dtype=bool, numpy=array([ True,  True,  True,  True])>
"""

t.gradient(y, x) == 2 * x

"""
<tf.Tensor: shape=(4,), dtype=bool, numpy=array([ True,  True,  True,  True])>
"""

2.5.4Python控制流的梯度计算

def f(a):
    b = a * 2
    while tf.norm(b) < 1000:
        b = b * 2
    if tf.reduce_sum(b) > 0:
        c = b
    else:
        c = 100 * b
    return c

a = tf.Variable(tf.random.normal(shape=()))
with tf.GradientTape() as t:
    d = f(a)
d_grad = t.gradient(d, a)
d_grad

"""
<tf.Tensor: shape=(), dtype=float32, numpy=512.0>
"""

d_grad == d / a

"""
<tf.Tensor: shape=(), dtype=bool, numpy=True>
"""

2.6.1 基本概率论

import numpy as np
import tensorflow as tf
import tensorflow_probability as tfp

fair_probs = tf.ones(6) / 6
tfp.distributions.Multinomial(1, fair_probs).sample()

"""
<tf.Tensor: shape=(6,), dtype=float32, numpy=array([0., 0., 0., 1., 0., 0.], dtype=float32)>
"""

tfp.distributions.Multinomial(10, fair_probs).sample()

"""
<tf.Tensor: shape=(6,), dtype=float32, numpy=array([3., 1., 1., 1., 2., 2.], dtype=float32)>
"""

counts = tfp.distributions.Multinomial(1000, fair_probs).sample()
counts / 1000

"""
<tf.Tensor: shape=(6,), dtype=float32, numpy=array([0.156, 0.185, 0.18 , 0.159, 0.173, 0.147], dtype=float32)>
"""

counts = tfp.distributions.Multinomial(10, fair_probs).sample(500)
cum_counts = tf.cumsum(counts, axis=0)
estimates = cum_counts / tf.reduce_sum(cum_counts, axis=1, keepdims=True)

plt.figure(figsize=(6, 4.5))
for i in range(6):
    plt.plot(estimates[:, i].numpy(), label=('P(die=' + str(i+1) + ")"))
plt.axhline(y=0.167, color='k', linestyle='--')
plt.gca().set_xlabel('Groups of experiments')
plt.gca().set_ylabel('Estimated probability')
plt.show()

posted @ 2023-03-17 23:10  lotuslaw  阅读(20)  评论(0编辑  收藏  举报