无监督学习(含自编码器在MNIST上的图片重建实战)

2023-10-26

目录

1. 无监督特征学习

             1.1. PCA (主成分分析)

       1.2. 稀疏编码 

       1.3. 自编码器

2. 自编码器在MNIST上的图片重建实战

3. 自编码器变种

          3.1 稀疏自编码器

       3.2. 堆叠自编码器

       3.3. 降噪自编码器

      3.4. 对抗自编码器

      3.5. 变分自编码器


      在现实应用中,机器学习的难点在于数据的标签难以获取。有时我们称这个工作为:数据标注工作。那有没有办法让机器来学习到数据本身的分布,是有的,我们称之为无监督学习。

        无监督学习是指从无标签的数据中学习出一些有用的模式,即只有x。

        无监督学习一般分为:

  • 无监督特征学习:一般用来降维,数据可视化,或是数据预处理。
  • 密度估计:根据一组样本来估计样本空间的概率密度。
  • 聚类:将一组训练样本,根据不同的规则划分至不同的组里面。

1. 无监督特征学习

        主要可分为:PCA、稀疏编码、自编码。

             1.1. PCA (主成分分析)

        是一种最常用的数据降维操作,使得在转换后的空间中的数据方差最大。假如现有一大堆东西其有很多成分构成,有些成分特别重要,有些则不。而我们需要做的工作就是把最重要的挖掘出来,所谓的降维就是将重要的特征取出来,然后特征的降低,即可以达到维度的降低。把高位数据集映射到低位空间中。

        PCA一般会用来做数据预处理,但是PCA并不能一定提高模型的准确性,因为在降维的时候,就已经有一定的信息丢失。即通过降维提高准确性是不很可靠的。

        因此PCA只是用在那种准确率本来就已经很高,我们可以使用PCA来实现模型的简化复杂度。对于太复杂的模型,PCA就可以实现即简单准确率又高。

        那么我们是怎么将 N维向量降到R维,并且保留大部分的信息呢?

        找到一条直线,使得两个特征的点在线上的产生映射,最后从二维降到一维。这条线的选取标准就是想让所有的点在线上的映射会足够的分散,即方差足够的大

        其他维度都是类似的。 先找第一个方向方差最大,之后找第二个方差最大。我们希望每个维度的信息相关性足够小,甚至完全不相关。即正交

        协方差可以表示两个维度的相关性,当协方差为0的时候就是正交,我们就说此时两变量是完全不相关的。

        总结就是在每个维度内,我们都希望方差是最大的(即点足够分散),但是维度之间,我们希望协方差为0(即特征之间尽可能没有关系)。即我们要找到R个正交基。同时每个维度方差足够大。

        如M*M -> N*M我们希望每行间的协方差=0,行内方差最大。

        用这样一个矩阵来表示各行之间协方差的关系:

         假设有一个原始矩阵:有一个X: M个N维的向量,原始协方差矩阵就是一个C: N*N的矩阵。我们需要的到一个Y : R*M的矩阵,它的协方差矩阵为:D : R*R。而协方差为0,就是希望对角线上的个每个元素(同一特征的而反差)都足够大而其它元素(每个元素之间的反差)都是0.

        实际上就是实现协方差矩阵的一个对角化。

         对D做一个推导:

        D = 1/M * Y * Y.T,   Y = R * M, 则D = R*R。

        我们需要一个变换矩阵:P(R,M)

        1. 需要一个X (N*M)矩阵。

        2. 01均值化。

        3. 求出协方差矩阵C。

        4. 求出协方差C的特征值(就是y每个元素的方差,从大到小沿对角线排列就可以构成D),和特征向量。

        5. 将特征向量,按照特征量的大小排序,按实际需要,降维的多少,需要的数据量是多少,得到一个降维的矩阵p。

        完整代码:

import numpy as np
import pandas as pd
import tensorflow as tf
import matplotlib.pyplot as plt 

class DimensionValueError(ValueError):
    """定义异常类"""
    pass

class PCA(object):
    """定义PCA类"""

    # n_components 可是是自己选的降维后的维度,也可以是PCA算法自动算出来他认为最优的维度(若不填)
    def __init__(self , x,n_components = None):
        """"x的数据结构应为: (ids,features)"""
        self.x = x
        self.dimension = x.shape[1]
        self.n_components = n_components
        # 希望降维后的维度小于原有的维度
        if n_components and n_components >= self.dimension:
            return DimensionValueError("n_components error")

    # x -> C
    def cov(self):
        """求x的协方差矩阵"""
        x_T = np.transpose(self.x) # 矩阵转置
        x_cov = np.cov(x_T)
        return x_cov

    #C -> 特征值和特征向量
    def get_feature(self):
        """求协方差矩阵C的特征值和特征向量"""
        x_cov = self.cov()
        a , b = np.linalg.eig(x_cov)
        m = a.shape[0]
        c = np.hstack((a.reshape((m,1)) , b)) # 得到特征值
        c_df = pd.DataFrame(c)
        c_df_sort = c_df.sort_values(0,ascending=False)
        return c_df_sort

    def explained_varience_(self):
        c_df_sort = self.get_feature()
        return c_df_sort.values[:,0]

    def paint_varience_(self):
        explained_varience_ = self.explained_varience_()
        plt.figure()
        plt.plot(explained_varience_,'k')
        plt.xlabel('n_components',fontsize=16)
        plt.xlabel('explained_varience_',fontsize=16)
        plt.show()

    def reduce_dimension(self):
        """根据指定维度降维/根据方差贡献率降维"""
        c_df_sort = self.get_feature()
        varience = self.explained_varience_()

        if self.n_components:
            p = c_df_sort.values[0:self.n_components,1:]
            y = np.dot(p,np.transpose(self.X)) #矩阵叉乘
            return np.transpose(y)

        varience_sum = sum(varience) #利用反差贡献率来自动选择降维后维度
        varience_radio = varience / varience_sum

        varience_contribution = 0
        for R in range(self.dimension):
            varience_contribution += varience_radio[R] #前R个反差贡献之和
            if varience_contribution >= 0.99: #前R个方差贡献度之和大于0.99,则认为前R个特征可以代表数据特征
                break

        p = c_df_sort.values[0:R + 1,1:] #取前R个特征维度
        y = np.dot(p,np.transpose(self.x)) #矩阵叉乘
        return np.transpose(y)

(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()

x = tf.reshape(x_train,shape=(-1,784))
x.shape

if __name__ == '__main__':
    pca = PCA(x)
    y = pca.reduce_dimension()
    print(y.shape)
    pca.paint_varience_()

       1.2. 稀疏编码 

        我们人收到外界刺激真正只是一少部分的神经元,感受到的一直是少数的局部特征,具有稀疏性,首次启发。有人提出稀疏编码的模型。

        线性编码:给定一组基向量A = [a1,a2……an],将输入样本x表示这些基向量的线性组合。

         如输入一张图片28*28,共784个点,输入的维度就是784,基向量是p,编码就是对D维空间的x找到其在p维空间的一个表示。每个基向量之间是独立的。输入样本可以通过Z和a重构出来。所以编码的主要工作找到一个完备的基向量a,PCA也是其中一个方法。但是PCA得到的一个向量是稠密的,没有稀疏性。

        为什么要强调稀疏性呢?就比如医生看病,也许生病有100种特征,医生诊断的时候只会根据几种来判断病因。但是这几种特征应该具有完备性。

        完备性:

        如果有p个基向量刚好能支撑p维的欧氏空间,则这p个向量是完备的。如果可支撑的维度d大于p的话,则这个基向量是过完备的。而稀疏编码得到目的是找到一组“超完备”的基向量来进行编码

        在此基础上,我们可以加入很多空的点,以此让他变得稀疏。

        稀疏编码的目标函数:

        我们怎么判断x输出的稀疏编码与x之间相差多少?最简单的方法之一就是l2范数。我们希望对应的稀疏编码Az能够尽量完全代表x。

        L(A,Z) = \sum_{n=1}^{N}(\left \| x^{(n)} - Az^{(n)} \right \|^{2}+\eta (z^{(n)}))

        稀疏性主要看\eta z^{(n)}部分,z^{(n)}是个系数衡量函数,当越稀疏,他的值就越小。最直接简单的的就是l0范数,即非0元素的个数,但是其不连续不可导,所以我们可以使用l1范数,即所有数的绝对值之和。即越靠近0的向量,就越接近稀编码。\eta是个超参数。

        在整个公式中,我们不知道的是A和z。怎么求呢?训练过程是:

        1. 固定基向量A,对每个输入的x,计算其对应的最优编码Z,即L(A,Z)为最小值的时候

        2. 固定上一步的得到的编码向量Z1,Z2……Zn,计算器最优的基向量A。


        稀疏编码的优点:

        1. 降低计算量。

        2. 可解释性,只有非常少数的非零元素,有生物的解释性。

        3. 实现特征的自动选择,只选择和输入样本相关的最少特征,从而更好地表示输入呀昂本,降低噪声,并减轻过拟合。

       1.3. 自编码器

        PCA或是稀疏编码本质上都是一个线性变换。那能不能通过神经网络这样一个非线性的方式来实现呢?神经网络一般训练方式需要一个输入x,以及标签y。那我们可不可以利用输入本身作为一个监督信号,从而指导网络的训练呢?即用f(x) -> x。

        为了实现这个目的,我们可以把网络分为两个部分:编码器,解码器。

        编码器:是将x得到一个映射关系,也相当与一个将降维的过程。

        解码器:是反过来得到与输入相同维度的向量。

        当然二者之间可以有很多隐藏层。

2. 自编码器在MNIST上的图片重建实战

import tensorflow as tf
import numpy as np
from tensorflow import keras
import matplotlib.pyplot as plt
from PIL import Image
tf.__version__

image_size = 28*28
h_dim = 20
num_epochs = 50
batch_size = 100
learning_rate = 1e-3
new_im = Image.new('L',(280,280))

(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
x_train , x_test = x_train.astype(np.float32)/255. , x_test.astype(np.float32)/255.
train_db = tf.data.Dataset.from_tensor_slices(x_train)
train_db = train_db.shuffle(batch_size*5).batch(128).batch(batch_size)

test_db = tf.data.Dataset.from_tensor_slices(x_test)
test_db = train_db.batch(batch_size)

class AE(keras.Model):
    '''自编码器模型'''
    def __init__(self):
        super().__init__()
        # 创建Encoder网络
        self.encoder = keras.Sequential([
            keras.layers.Dense(256,activation='relu'),
            keras.layers.Dense(128,activation='relu'),
            keras.layers.Dense(h_dim),
        ] , name='decoder')

        # 创建Decoder网络
        self.decoder = keras.Sequential([
            keras.layers.Dense(128,activation='relu'),
            keras.layers.Dense(256,activation='relu'),
            keras.layers.Dense(image_size),
        ])
    def call(self, inputs, training=None, mask=None):
        # 编码
        h = self.encoder(inputs)
        # 解码
        x_hat = self.decoder(h)
        return x_hat

model = AE()
model.build(input_shape=(None,image_size))
model.summary()

for epoch in range(num_epochs):
    for step, x in enumerate(train_db):
        # step划分成批次的批次数,x就是[100,28,28]
        x = tf.reshape(x, [-1,784])
        with tf.GradientTape() as tape:
            # 前向传播
            x_reconstruction_logits = model(x) # 类似于通过前向传播求出的 预估值
            # 计算loss
            reconstruction_loss = tf.nn.sigmoid_cross_entropy_with_logits(labels=x,logits=x_reconstruction_logits)
            #对100张图片求出平均的loss
            reconstruction_loss = tf.reduce_mean(reconstruction_loss)
        # 自动求导
        gradients = tape.gradient(reconstruction_loss ,model.trainable_variables)
        # 自动更新
        tf.optimizers.Adam(learning_rate).apply_gradients(zip(gradients,model.trainable_variables))

        if epoch % 100 == 0:
            print("epoch: ",epoch," step: ",step," loss: ",reconstruction_loss)

    #每次迭代完成后,构建图片进行比较
    out_logits = model(x[:batch_size//2])
    out = tf.nn.sigmoid(out_logits)
    out = tf.reshape(out, [-1,28,28]).numpy() * 255.

    x = tf.reshape(x[:batch_size // 2], [-1,28,28])
    x_concat = tf.concat( [x,out] ,axis = 0).numpy() * 255.
    x_concat = x_concat.astype(np.uint8)

    index = 0
    for i in range(0,280,28):
        for j in range(0,280,28):
            im = x_concat[index]
            im = Image.fromarray(im,mode='L')
            new_im.paste(im,(i,j))
            index += 1

    new_im.save('images/_%d.png' % (epoch))
    plt.imshow(np.asarray(new_im))
    plt.show()
    print('new image saved !')

# 取测试机中的一个批次的图片
x = next(iter(test_db))

3. 自编码器变种

          3.1 稀疏自编码器

        给自编码器的隐藏层z上增加了稀疏性限制,希望编码层的输出维度大于输入的维度。

        

         公式中的稀疏性限制ρ可以是KL散度。是神经元激活的概率。

       3.2. 堆叠自编码器

        通过逐层堆叠的方式训练一个深层的自编码器。

        由于深层的网络会发生过拟合,以及参数量过大。我们就可以使用Droupout编码器,混合使用,来降低过拟合。

       3.3. 降噪自编码器

        给输入数据随即增加一些噪声,随机的将x的一些维度值设置为0,得到一个被破坏的向量x。

      3.4. 对抗自编码器

        通过任意先验分布与VAE隐藏代码向量的聚合后验匹配。将聚合后的后验与先验相匹配,确保从先验空间的任何部分产生的样本是有意义的。

        原来的自编码器是实值与实值的比较,而变分自编码器,是将实值用概率值的方式考虑。实际上变分自编码器VAE是普通自编码器与贝叶斯模型的混合。

      3.5. 变分自编码器

        原来的自编码器,本质上是给定一个x,我们找到一个映射关系到Z。这本质上是一个判别模型,最后z解码后生成的x’本质上还是x生成的。那我们能不能通过隐藏的z来生产一个x‘呢?

        可以从x得到隐变量z相应的一些概率分布。通过全概率分布p(x) = p(x|z)p(z),则可以得到一个p(x)的概率分布。

        假设服从正态分布的Z,在生成器decoder的作用下,可以生成新的样本。那新的样本和原来的分布是否相等呢?

         我们不能用KL散度来计算分布是否相等。

         z(隐变量)可以理解为是有可能影响分布的一些可能性。生成的x肯定也会有一些z的特性

         上述公式,假设p(z)是满足正态分布的,而p(x|z):即贝叶斯公式。

        而公式中的p(z|x)可以用变分推断的方式,用一个q(z|x)来逼近,因为可以证明,总有方法使得一个映射到另一个概率分布。我们可以用KL散度来比较两种分布的差距。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无监督学习(含自编码器在MNIST上的图片重建实战) 的相关文章

  • Django Rest Framework 嵌套序列化器不显示相关数据

    我使用 Django Rest Framework 进行了基本设置 我有两个模型和一个嵌套序列化器设置 models py from django db import models class Plan models Model name
  • 如何在 Pygame 中制作边框

    我试图让游戏的某个区域周围有边框 并使用一种尺寸来不断更改我的代码 以便它适用于一种尺寸 这是代码 screen xpos ypos height width border width color def draw borders s x
  • 如何让我的精灵向鼠标位置发射一个对象?

    对于一个学校项目 我需要通过实现一种向鼠标位置射击 Kunais Shurikens 的方式来完成下面的 pygame 程序 以便能够击中敌人精灵 import pygame import math import random from p
  • ImportError:尝试在没有已知父包的情况下进行相对导入[重复]

    这个问题在这里已经有答案了 我正在学习使用 python 编程 并且在从包中的模块导入时遇到问题 我正在使用 Visual Studio 代码和 Python 3 8 2 64 位 我的项目目录 https i stack imgur co
  • 如何从字符串读取 NumPy 二维数组?

    如何从字符串中读取 Numpy 数组 取一个像这样的字符串 0 5544 0 4456 0 8811 0 1189 并将其转换为数组 a from string 0 5544 0 4456 0 8811 0 1189 where a成为对象
  • 对自定义类进行排序而不使用“key”参数?

    您可以对数组进行排序myclass通过使用key论证sorted功能 sortedlist sorted myclasses key lambda obj obj myproperty 有没有办法为我们的班级定义自然顺序 也许有一些神奇的方
  • 在 Python 中打开文本文件时出现问题

    这看起来应该很简单 f open C Users john Desktop text txt r 但我收到此错误 Traceback most recent call last File
  • 用户在对话框中输入

    python 中是否有任何库可用于图形用户输入 我知道关于tk但我相信需要一些代码才能做到这一点 我正在寻找最短的解决方案 a input Enter your string here 取而代之的是 我想要一个对话框 以便用户可以在那里输入
  • Python 中的类位于不同的文件中吗?

    与 Java 或 php 非常相似 我习惯将类与文件分开 Python 中也是同样的情况吗 另外 我应该如何命名该文件 像classname py一样小写还是像ClassName py一样 如果我想从此类创建一个对象 我是否需要做一些特殊的
  • 使用 QtDesigner 的 pyQt 信号/槽

    我正在尝试编写一个与 QGraphicsView 交互的程序 我想在 QGraphicsView 中发生事件时收集鼠标和键盘事件 例如 如果用户单击 QGraphicsView 小部件 我将获得鼠标位置 类似的东西 我可以很容易地对其进行硬
  • AMD plaidml 与 CPU Tensorflow - 意外结果

    我目前正在运行一个简单的脚本来训练mnist数据集 通过 Tensorflow 通过我的 CPU 运行训练给了我49us sample和使用以下代码的 3e 纪元 CPU import tensorflow as tf mnist tf k
  • 向类添加属性的更 Pythonic 方式?

    我正在使用来自两个不同网页的数据集 但对于同一个人 数据集是合法信息 一些数据在第一页上可用 因此我使用正确的信息初始化被告对象 并将我当前没有数据的属性设置为null 这是班级 class Defendant object holds d
  • 将字符串作为有序字典导入

    我有一个没有扩展名的文件 其中包含这样的行 忽略行之间的间距 但每一行都是单独的行 OrderedDict key1 u value1 key2 value2 OrderedDict key1 u value1 key2 value2 Or
  • 如何更新 certifi 的根证书?

    我正在使用 certifi python 模块来验证 ssl 连接 我查看了 certifi python2 7 site packages certifi cacert pem 中包含的根证书 其中一些证书已过期 我如何更新这些证书 我尝
  • Linux 中如何确定哪个进程正在使用某个端口

    我目前正在其默认端口上运行 RethinkDB 因为如果我将浏览器指向localhost 8080我看到 RethinkDB Web 界面 我想关闭 RethinkDB 并使用以下命令在另一个端口上重新打开它 port offset争论 然
  • 如何提取数字(以及比较形容词或范围)

    我正在用 Python 开发两个 NLP 项目 它们都有类似的任务提取数值和比较运算符来自句子 如下所示 greater than 10 weight not more than 200lbs height in 5 7 feets fas
  • pytube 在 Android 中传输视频所需的时间太长

    我在用pytube在 Android 中流式传输视频 借助chaquopy 视频文件 py from pytube import YouTube def video link yt YouTube f https www youtube c
  • 在matplotlib中绘制曲线连接点

    所以我试图绘制曲线来连接点 这是我正在使用的代码 def hanging line point1 point2 a point2 1 point1 1 np cosh point2 0 np cosh point1 0 b point1 1
  • 导入后属性未添加到模块中

    我做了以下实验室 vagrant ubuntu xenial test tree pack1 init py mod1 py pack2 init py mod2 py mod3 py test py 2 directories 6 fil
  • 用 Ruby 或 Python 解析 SVG 的库 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 SVG 是一个庞大的标准 它基于 XML 我过去曾将 SVG 解析为 XML 然而 有些事情很难 例如

随机推荐

  • 刀片服务器切换显示,刀片机服务器切换

    刀片机服务器切换 内容精选 换一换 当保护组的生产站点发生故障时 将保护组的生产站点切到当前的容灾站点 即另一端AZ 启用当前容灾站点的云硬盘以及云服务器等资源 故障切换完成之后 保护组的当前生产站点变成故障切换发生之前的容灾站点 且生产站
  • 大数据开源框架之HBase编程实践

    HBase的安装部署请看 30条消息 大数据开源框架环境搭建 五 Hbase完全分布式集群的安装部署 木子一个Lee的博客 CSDN博客 目录 任务1 用HBase提供的HBase Shell命令实现以下指定功能 1 列出HBase所有的表
  • 我的创作纪念日

    机缘 我热爱编程 热爱解决问题 也享受在解决问题的过程中遇到的挑战 在大学的学习过程中 我发现将学习过程和解决问题的过程记录下来能够帮助我更深入地理解知识和技术 同时也为未来遇到类似问题提供了参考 我开始将我的学习笔记分享给同学们 收到了非
  • 二维矩形装箱问题

    装箱问题 是个NP问题 至于装箱问题到底是个什么东西 可以看看百度文档http wenku baidu com view f6e7f80590c69ec3d5bb755f html 其实我没看 研究二维矩形装箱问题 是因为需要将小图拼成大图
  • JAVA使用socket outputstream中碰到的问题

    今天在使用java的socket写网络通信 作为服务端向对端传送数据 建立连接后 首先发4个字节的内容 存放文件大小 然后再发送文件正文内容 代码是这样写的 Socket client new Socket 192 168 60 1 999
  • 谈谈Elasticsearch 和 传统关系型数据库的对比

    本帖最后由 mtsbv110 于 2016 3 22 15 03 编辑 1 在Elasticsearch中 文档归属于一种 类型 type 而这些类型存在于 索引 index 中 类比传统关系型数据库 Relational DB gt Da
  • PaddleOCR系列-训练模型并部署android手机

    PaddleOCR系列 训练模型并部署android手机 TOC PaddleOCR系列 训练模型并部署android手机 1 训练paddleocr模型 2 ocr模型部署安卓手机 2 1 AndroidStudio 2021 2 1或以
  • RecyclerView详解

    RecyclerView 简称 RV 是作为 ListView 和 GridView 的加强版出现的 目的是在有限的屏幕之上展示大量的内容 因此 RecyclerView 的复用机制的实现是它的一个核心部分 RV 常规使用方式如下 解释说明
  • ARM开发板挂接NFS网络文件系统

    1 交叉线连开发板和PC 2 LINUX IP PC IP和开发板IP属同一网段 LINUX IP 192 168 1 20 PC IP 192 168 1 30 做中转作用 开发板IP 192 168 1 10 3 ubuntu默认是没有
  • mysql 建表语句 stored as_Druid 解析Hive建表语句解析报错

    Druid 版本 com alibaba druid spring boot starter 1 2 3 Hive 建表SQL create table ads data sale detail one23 like ads data sa
  • HashMap的底层实现原理

    HashMap的底层实现原理 一 HashMap的底层实现原理 HashMap 在 JDK1 8 之前的实现方式 数组 链表 JDK1 8之后的实现方式 数组 链表 红黑树 原理 当你 new 一个 HashMap 的时候 它底层并没有创建
  • 有哪些副业适合教师?有哪些是教师禁止的副业?

    有哪些副业适合教师 有哪些是教师禁止的副业 老师做副业选择挺多的 但是很多人一上来就说什么辅导班 做点小生意之类的 大家怕是还不知道对于在编教师有些兼职副业是做不了的 有些事没有禁止可以做的 还有一些是鼓励做的 那些副业是老师坚决不能碰的
  • Java初学之标识符

    目录 一 什么是标识符 二 标识符的命名规则 三 标识符的命名规范 一 什么是标识符 标识符 identifier 是指用来标识某个实体的一个符号 在不同的应用环境下有不同的含义 在java源程序中 凡是程序员有权利自己命名的单词都是标识符
  • 关于数据导入,教你几招

    前言 我们知道 数据库是存放数据的仓库 日常我们使用数据库也是为了存储数据 和数据库打交道总免不了要进行数据导入工作 工作中也可能遇到各种不同的数据导入需求 本篇文章主要分享下数据导入相关的小技巧 希望你能学到几招 1 弄清需求是关键 在进
  • AIX 常用命令

    查看所有vg对应的lv lsvg o lsvg i l 查看一个lv的详细细心 lv对应的日志文件 getlvcb AT fslv01 VGDA与ODM的同步 synclvodm v vght vg 名字 umount被占用删除 fuser
  • TortoiseGit 入门指南05:推送和拉取

    本节所讲内容均涉及到 远端版本库 版本库 的概念在 TortoiseGit 入门指南02 创建和克隆仓库 中提到过 它是工作目录下面的一个名为 git 的隐藏目录 我们每一次提交 每一个分支都会保存在版本库中 这个版本库就在我们电脑上的某个
  • C算法:冒泡排序算法(超级详细)!!!

    冒泡排序算法 冒泡排序是一种简单的排序算法 它也是一种稳定排序算法 其实现原理是重复扫描待排序序列 并比较每一对相邻的元素 当该对元素顺序不正确时进行交换 一直重复这个过程 直到没有任何两个相邻元素可以交换 就表明完成了排序 一般情况下 称
  • 常用的三种代码宏定义

    常用的三种代码宏定义 方式一 if endif 方式二 ifdef endif 方式一 if和方式二 ifdef别混搅 方式三 ifndef define else endif 方式一 if endif define LEDTEST 1 1
  • 文件解压缩操作

    文件解压缩操作 package com general system import java io File import java io FileOutputStream import java io IOException import
  • 无监督学习(含自编码器在MNIST上的图片重建实战)

    目录 1 无监督特征学习 1 1 PCA 主成分分析 1 2 稀疏编码 1 3 自编码器 2 自编码器在MNIST上的图片重建实战 3 自编码器变种 3 1 稀疏自编码器 3 2 堆叠自编码器 3 3 降噪自编码器 3 4 对抗自编码器 3