可以首先参考这篇文章
bit是bit位,也就是一个0或者1占据的空间, 也就是最小的存储单元。 千位: Kbits
Byte是字节,为计算机存储容量大小的及基本计算单位。千字节: Kbytes (KB)我们通常说的 硬盘400GB,这里的B指的是Byte也就是字节。一般使用字节(KB)来表示文件的大小。
M表示数值,不是单位,MB是量单位,兆字节,这个B是Byte而不是bit。Mb一般指兆位。
注意:小k通常表示1000,大K表示1024
1Byte=8bit
1KB=1024B=1024*8b
1kB=1000B=1000*8b
1Kb=1024b
1kb=1000b
1MB=1024KB
1GB=1024MB
1T=1024GB
其他需要注意的地方:
在这里需要说明的问题是在单位换算上有一点是极其重要的,即:
1Mb=1024kb=1024000b
1MB=1024KB=1024*1024B=1024*1024*8b=8388608b这在数量上差的很多
1KB=1024B(大写K)
1kB=1000B(小写k)
1Mbps=1Mb=1024kb ,1024/8=128kb/s.
cd表格中数据需要换算为下来标准单位
每帧的数据大小:KB/frame (VHCD/8/1000) 每秒的数据流量:Mbps or Kbps 每像素的数据量:bytes/pixel 帧率: fps(Frames Per Second: 1秒时间内传输的图片的帧数)
*补充: 每秒的数据流量也可称为码率,Mbps为兆位每秒,更常见的是在传输过程中与字节打交道,需要除以8,比如 100Mbps=100/8=12.5MB/s, 100Kbps=100/8=12.5KB/s.
其实回溯法的套路是非常固定的,是一种决策树的表现形式。
形式:
result = {};
void backtrack(路径, 选择列表){
if (满足条件)
result.add(路径);
return;
for (if 路径 in 选择列表){
做选择
backtrack(路径,选择列表);
撤销选择
}
}
以 LeetCode # 113 Path Sum II为例,题目给你一个sum,要求保存从root到leaf的累加和等于该sum的路径:
[
[5,4,11,2],
[5,8,4,5]
]
看下下面这段优秀的代码:
class Solution {
public:
vector<vector<int>> pathSum(TreeNode* root, int sum) {
vector<vector<int>> res;
vector<int> path;
findPaths(res, path, root, sum);
return res;
}
private:
void findPaths(vector<vector<int>> &paths, vector<int> &path, TreeNode *cur, int sum){
if(!cur) return ;
path.push_back(cur->val); // 这就是细节
if(!(cur->left) && !(cur->right) && (cur->val == sum))
paths.push_back(path); // 满足条件,
if(cur->left) findPaths(paths, path, cur->left, sum - cur->val);
if (cur->right) findPaths(paths, path, cur->right, sum - cur->val); // 选择列表
path.pop_back(); // 撤销不满足的节点值
}
};
有了最基本的框架,剩下的就是一些细节了,需要编程经验的积累。 照着葫芦画瓢,下面是全排列的代码:
class Solution {
public:
vector<vector<int>> permute(vector<int>& nums) {
vector<vector<int>> res;
vector<int> track;
permutations(res, nums, track);
return res;
}
private:
void permutations(vector<vector<int>>& res, vector<int>& nums, vector<int>& track){
if (track.size() == nums.size()){
res.push_back(track);
return;
}
for (int i = 0; i < nums.size(); i++){
if (std::find(track.begin(), track.end(), nums[i])!=track.end()) {
continue; // 在vector中判断是否存在一个元素
}
track.push_back(nums[i]);
permutations(res, nums, track);
track.pop_back();
}
}
};
在学习audio的过程中,经常会遇到PCM这个设备,那什么是PCM?跟随下面的这个链接: https://blog.csdn.net/cc289123557/article/details/78745277 来看一下这个特有名词.
脉冲编码调制(Pulse Code Modulation,PCM),就是把一个时间连续,取值连续的模拟信号变换成时间离散,取值离散的数字信号后在信道中传输,这是基本原理。 根据此原理,在音频领域的数字音频就用pcm设备来代表,pcm也是一种音频格式,可以自定义通道数,采样率,采样精度;我们经常采用的I2S格式其实属于pcm的一种,不过I2S规定了只有2通道。 音频的采样率(rate)一般采用44.1K,16K,48K等,采样精度(format)一般都是8/16/24/32bit
kernel结构体设备:
struct snd_pcm
struct snd_pcm_str
struct snd_pcm_substream
一个音频设备分播放和录音两个功能,对应到pcm就分PLAYBACK和CAPTURE,分别用结构体snd_pcm_str来表示,一个播放或者录音设备可以集成多个音频流,每个音频流用snd_pcm_substream结构体来表示 好,引用到此结束。
今天我们不聊kernel,只关注上层的应用。在ALSA(Advanced Linux Sound Architecture)中, pcm代表了一个通路。
总结来说就是, pcm设备就是kernel的抽象层,可以把计算机硬件声卡采集到的物理特性进行描述,正如上面的通道数、采样率、采样精度等。
这块属于ALSA-lib的东西了。包含一套插件机制,可以对audio进行 resampling、mixing、channel mapping等操作,
Pulseaudio作为sound server负责集成处理各种声卡的输入输出信号。目前各大linux发行版默认安装PulseAudio了。
usage 1:
aplay -c 2 -t wav cut.wav
正在播放 WAVE 'cut.wav' : Signed 16 bit Little Endian, 频率44100Hz, Stereo
这个命令可以把名为cut.wav的音乐文件使用aplay播放出来。”-c 2”是2通道, -t指明类型,但是在我这里改变通道的效果没有体现出来。
这两个工具在使用的过程中遇到的一个问题是,”-L”参数只会列出该pc中的芯片设备,当你插入一个mic,并不会自己分辨出 哪个是刚才插入的mic.
arecord -L
default
Playback/recording through the PulseAudio sound server
null
Discard all samples (playback) or generate zero samples (capture)
pulse
PulseAudio Sound Server
sysdefault:CARD=PCH
HDA Intel PCH, CX20632 Analog
Default Audio Device
front:CARD=PCH,DEV=0
HDA Intel PCH, CX20632 Analog
Front speakers
dmix:CARD=PCH,DEV=0
HDA Intel PCH, CX20632 Analog
Direct sample mixing device
dmix:CARD=PCH,DEV=2
HDA Intel PCH, CX20632 Alt Analog
Direct sample mixing device
dsnoop:CARD=PCH,DEV=0
HDA Intel PCH, CX20632 Analog
Direct sample snooping device
dsnoop:CARD=PCH,DEV=2
HDA Intel PCH, CX20632 Alt Analog
Direct sample snooping device
hw:CARD=PCH,DEV=0
HDA Intel PCH, CX20632 Analog
Direct hardware device without any conversions
hw:CARD=PCH,DEV=2
HDA Intel PCH, CX20632 Alt Analog
Direct hardware device without any conversions
plughw:CARD=PCH,DEV=0
HDA Intel PCH, CX20632 Analog
Hardware device with all software conversions
plughw:CARD=PCH,DEV=2
HDA Intel PCH, CX20632 Alt Analog
Hardware device with all software conversions
通过man函数可知,这里面包含有soundcards和 digital sound devices 参考: https://sysplay.in/blog/tag/arecord/
其实这里有一个问题就是,“-L”参数并不会出现类似上面URL的资料,只有一个-l
才可以。
vimer@host:~/pic/vs$ arecord -l
**** CAPTURE 硬體裝置清單 ****
card 0: Loopback [Loopback], device 0: Loopback PCM [Loopback PCM]
子设备: 7/8
子设备 #0: subdevice #0
子设备 #1: subdevice #1
子设备 #2: subdevice #2
子设备 #3: subdevice #3
子设备 #4: subdevice #4
子设备 #5: subdevice #5
子设备 #6: subdevice #6
子设备 #7: subdevice #7
card 0: Loopback [Loopback], device 1: Loopback PCM [Loopback PCM]
子设备: 8/8
子设备 #0: subdevice #0
子设备 #1: subdevice #1
子设备 #2: subdevice #2
子设备 #3: subdevice #3
子设备 #4: subdevice #4
子设备 #5: subdevice #5
子设备 #6: subdevice #6
子设备 #7: subdevice #7
card 1: PCH [HDA Intel PCH], device 0: CX20632 Analog [CX20632 Analog]
子设备: 0/1
子设备 #0: subdevice #0
card 1: PCH [HDA Intel PCH], device 2: CX20632 Alt Analog [CX20632 Alt Analog]
子设备: 1/1
子设备 #0: subdevice #0
这里有一个问题值得注意,这里的loopback有很好玩的东西在里面。在一个终端上:
vimer@host:~/pic/vs$ arecord -D hw:0,1,4 -f S16_LE -c 2 -r 48000 recorded.wav
正在录音 WAVE 'recorded.wav' : Signed 16 bit Little Endian, 频率48000Hz, Stereo
然后新开一个终端,这两个shell terminator谁前谁后无所谓的。
aplay -D hw:0,0,4 cut.wav
正在播放 WAVE 'cut.wav' : Signed 16 bit Little Endian, 频率44100Hz, Stereo
警告:频率不精确(要求=44100Hz,收到=48000Hz)
请尝试plug插件
这个时候, 在第一个终端里的recorded.wav就保存了第二个终端里的 cut.wav 的audio。
尤其注意这里的 -D
参数, hw:card-id,devices-id,subdevices-id
.总结出来的一个规律就是 playback 和 capture 得是同一个 card-id, 不同的devices-id, 相同的 subdeviced-id ,其中, subdevices-id 从0到7.
类似这样:
#include <stdio.h>
int main(int argc, char **argv) {
char *cmd = "arecord -D plughw:0 -f S16_LE -c 1 -r 16000 -t raw -q -";
char buf[256];
FILE *fp = popen(cmd, "r");
for (int i=0; i<16; i++) {
int result = fread(buf, 1, sizeof(buf), fp);
printf("read %d bytes\n", result);
}
pclose(fp);
return 0;
}
参考: https://zhuanlan.zhihu.com/p/58834651
为什么这么说呢?主要是因为自己在pc上(尤其是内置网卡的这种),经常会遇到插上耳机无法读取输入声音的情况,也不知道为什么?
这里做一个比较好的澄清:
输出设备,也就是所谓的喇叭,如果内置了扬声器,在我使用Ubuntu观察到的情况是,插上耳机后,系统默认使用一个模拟耳机/内置音频
的输出项。如果我把耳机拔出来,则系统就会把刚才那个名称变化为扬声器/内置音频
。
总结: 如果不插入耳机,则是使用内置的扬声器,如果通过mic口插入耳机,则会是模拟耳机。
同样的情况出现在 话筒。我们现在的情况很特殊,没有内置话筒,插上带有讲话功能的耳机后出现 话筒 内置音频的变化。
这也是一个很实用的命令,可以让你对整体的输入输出设备有一个清晰的理解。
pacmd
Welcome to PulseAudio 11.1! Use "help" for usage information.
>>> list-links
Unknown command: list-links
>>> ^[[A^[[D
>>> own command:
>>> list-sinks
2 sink(s) available.
index: 1
name: <alsa_output.platform-snd_aloop.0.analog-stereo>
driver: <module-alsa-card.c>
flags: HARDWARE HW_VOLUME_CTRL DECIBEL_VOLUME LATENCY DYNAMIC_LATENCY
state: SUSPENDED
suspend cause: IDLE
priority: 9009
volume: front-left: 26006 / 40% / -24.08 dB, front-right: 26006 / 40% / -24.08 dB
balance 0.00
base volume: 65536 / 100% / 0.00 dB
volume steps: 65537
muted: no
current latency: 0.00 ms
max request: 0 KiB
max rewind: 0 KiB
monitor source: 2
sample spec: s16le 2ch 44100Hz
channel map: front-left,front-right
立体声
used by: 0
linked by: 0
configured latency: 0.00 ms; range is 0.50 .. 2000.00 ms
card: 1 <alsa_card.platform-snd_aloop.0>
module: 28
properties:
alsa.resolution_bits = "16"
device.api = "alsa"
device.class = "sound"
alsa.class = "generic"
alsa.subclass = "generic-mix"
alsa.name = "Loopback PCM"
alsa.id = "Loopback PCM"
alsa.subdevice = "0"
alsa.subdevice_name = "subdevice #0"
alsa.device = "0"
alsa.card = "0"
alsa.card_name = "Loopback"
alsa.long_card_name = "Loopback 1"
alsa.driver_name = "snd_aloop"
device.bus_path = "platform-snd_aloop.0"
sysfs.path = "/devices/platform/snd_aloop.0/sound/card0"
device.form_factor = "internal"
device.string = "front:0"
device.buffering.buffer_size = "352800"
device.buffering.fragment_size = "352800"
device.access_mode = "mmap+timer"
device.profile.name = "analog-stereo"
device.profile.description = "模拟立体声"
device.description = "内置音频 模拟立体声"
alsa.mixer_name = "Loopback Mixer"
module-udev-detect.discovered = "1"
device.icon_name = "audio-card"
ports:
analog-output: 模拟输出 (priority 9900, latency offset 0 usec, available: unknown)
properties:
active port: <analog-output>
* index: 3
name: <alsa_output.pci-0000_00_1f.3.analog-stereo>
driver: <module-alsa-card.c>
flags: HARDWARE HW_MUTE_CTRL HW_VOLUME_CTRL DECIBEL_VOLUME LATENCY DYNAMIC_LATENCY
state: SUSPENDED
suspend cause: IDLE
priority: 9039
volume: front-left: 25486 / 39% / -24.61 dB, front-right: 25486 / 39% / -24.61 dB
balance 0.00
base volume: 65536 / 100% / 0.00 dB
volume steps: 65537
muted: no
current latency: 0.00 ms
max request: 0 KiB
max rewind: 0 KiB
monitor source: 5
sample spec: s16le 2ch 44100Hz
channel map: front-left,front-right
立体声
used by: 0
linked by: 0
configured latency: 0.00 ms; range is 0.50 .. 371.52 ms
card: 0 <alsa_card.pci-0000_00_1f.3>
module: 7
properties:
alsa.resolution_bits = "16"
device.api = "alsa"
device.class = "sound"
alsa.class = "generic"
alsa.subclass = "generic-mix"
alsa.name = "CX20632 Analog"
alsa.id = "CX20632 Analog"
alsa.subdevice = "0"
alsa.subdevice_name = "subdevice #0"
alsa.device = "0"
alsa.card = "1"
alsa.card_name = "HDA Intel PCH"
alsa.long_card_name = "HDA Intel PCH at 0x4000100000 irq 141"
alsa.driver_name = "snd_hda_intel"
device.bus_path = "pci-0000:00:1f.3"
sysfs.path = "/devices/pci0000:00/0000:00:1f.3/sound/card1"
device.bus = "pci"
device.vendor.id = "8086"
device.vendor.name = "Intel Corporation"
device.product.id = "a348"
device.form_factor = "internal"
device.string = "front:1"
device.buffering.buffer_size = "65536"
device.buffering.fragment_size = "32768"
device.access_mode = "mmap+timer"
device.profile.name = "analog-stereo"
device.profile.description = "模拟立体声"
device.description = "内置音频 模拟立体声"
alsa.mixer_name = "Conexant CX20632"
alsa.components = "HDA:14f15098,103c8596,00100100 HDA:8086280b,80860101,00100000"
module-udev-detect.discovered = "1"
device.icon_name = "audio-card-pci"
ports:
analog-output-lineout: 线缆输出 (priority 9900, latency offset 0 usec, available: no)
properties:
analog-output-speaker: 扬声器 (priority 10000, latency offset 0 usec, available: no)
properties:
device.icon_name = "audio-speakers"
analog-output-headphones: 模拟耳机 (priority 9000, latency offset 0 usec, available: yes)
properties:
device.icon_name = "audio-headphones"
active port: <analog-output-headphones>
>>>
可以看到,模拟耳机现在是可以使用的。active port
这也是一个最明显的提示。
目前,经过n多次的实验,终于可以将mic(耳机的声音传进来了), 也就是可以使用arecord命令行进行录音了。还是老问题,首先在 Ubuntu 的声音设置中,在 input 中选择正确的物理设备。我这里是插上耳机机会显示:
话筒/内置音频
然后使用命令:
arecord -d 10 -c 2 -r 48000 -f S16_LE my.wav
# 正在录音 WAVE 'my.wav' : Signed 16 bit Little Endian, 频率48000Hz, Stereo
这个时候就会录制一段时间为10s, 2通道(Stereo) 采样率为48Khz, format为S16_LE的名为 my.wav的录音,然后你就可以使用 aplay 取播放它了。
当然,是从默认mic啦(如果插入耳机的话就是耳机了)
aplay my.wav
现在还有一个问题就是没法指定设备取录音,假设加上 hw:0,0 则不会录制声音。
注意这篇文章,基本上涵盖了线性代数的方方面面。
开门说,三个inputs影响一个决定,这三个inputs可以使用权重去影响。
卷积神经网络中每层卷积层(Convolutional layer)由若干卷积单元组成,每个卷积单元的参数都是通过反向传播算法最佳化得到的。卷积运算的目的是提取输入的不同特征,第一层卷积层可能只能提取一些低级的特征如边缘、线条和角等层级,更多层的网路能从低级特征中迭代提取更复杂的特征。
有关反向传播的说明请看这篇文章: article 基本上的意思就是利用一个激活函数=>sigmoid 函数,反向的把输入参数的权重进行调整,使输出与结果预期差不太多。
可以看这边中文, 其中文中的参考, 直接看英文就行了,这样就齐全了。
Convolution is using a ‘kernel’ to extract certain ‘features’ from an input image. Let me explain. A kernel is a matrix, which is slid across the image and multiplied with the input such that the output is enhanced in a certain desirable manner.
这里还有一个kernel及filter的概念区别。再澄清一次,kernel就是一个权重矩阵,利用矩阵的乘法,将输入的image提取出特征值。矩阵的维度也就是该神经网络的维度.
而filter则是多个kernel的”拼接”,我也不知道使用这个名词怎么样,其中,这里面的每一层kernel都被赋予为特殊的输入通道。Filter一直比kernel多一维,
So for a CNN layer with kernel dimensions hw and input channels k, the filter dimensions are kh*w.
1D卷积网络基本上处理的是时间序列,因为一维的嘛,假设input是1D的,好多个连续数据,然后经过filter后就可以转化为1D output的其中一个。
本blog暂时还不能上传图片,所以还是用文字描述。input层,就是有多个channel,然而filter也是几层kernel合并在一起,这两者进行某些数学计算从而一个二维的输出。 这个model大部分被用于计算机视觉领域。
线性整流层(Rectified Linear Units layer, ReLU layer)使用线性整流(Rectified Linear Units, ReLU), f(x) = max(0, x).
以上来自百度百科。
pooling池化的作用则体现在降采样:保留显著特征、降低特征维度,增大kernel的感受野。另外一点值得注意:pooling也可以提供一些旋转不变性。
池化层可对提取到的特征信息进行降维,一方面使特征图变小,简化网络计算复杂度并在一定程度上避免过拟合的出现;一方面进行特征压缩,提取主要特征。 最大池采样在计算机视觉中的价值体现在两个方面:(1)、它减小了来自上层隐藏层的计算复杂度;(2)、这些池化单元具有平移不变性,即使图像有小的位移,提取到的特征依然会保持不变。由于增强了对位移的鲁棒性,这样可以忽略目标的倾斜、旋转之类的相对位置的变化,以此提高精度,最大池采样方法是一个高效的降低数据维度的采样方法。 需要注意的是:这里的pooling操作是特征图缩小,有可能影响网络的准确度,因此可以通过增加特征图的深度来弥补(这里的深度变为原来的2倍)。
在CNN网络中卷积池之后会跟上一个池化层,池化层的作用是提取局部均值与最大值,根据计算出来的值不一样就分为均值池化层与最大值池化层,一般常见的多为最大值池化层。池化的时候同样需要提供filter的大小、步长。
https://www.cnblogs.com/eilearn/p/9282902.html
池化层夹在连续的卷积层中间, 用于压缩数据和参数的量,减小过拟合。简而言之,如果输入是图像的话,那么池化层的最主要作用就是压缩图像。
对卷积层来说,其会从高、宽和深,三个维度均改变原始像素矩阵的维度,特别是深度方面的维度,由卷积核的数量所决定。。而对于池化层来说,池化层只是在高和宽的方向上对像素矩阵进行改变,深度方向不存在变化(没有池化矩阵个数的概念)。。你说得很好,卷积核的参数受到反向传播的影响,每次迭代均会改变,而对于池化层,并没有迭代过程中的参数调整。。同时,由于对物体边缘而言,其像素值一般都较大,通过最大池化,便可以保留关键信息。
参考这篇文章: https://blog.csdn.net/weixin_38145317/article/details/89310404
如果涉及到non local去噪算法的话,patch表示某一点关联的一片区域(正方形区域),而点和点之间的权要用到patch和patch之间的距离,然后把搜索区域内的点加权平均,
在超分辨率重建中,patch是图像片,如33或55大小的片。得看具体的应用背景。
通过阅读,“patch”似乎是CNN输入图像的其中一小块,但它究竟是什么呢?当使用CNN解决问题时,“patch”什么时候开始起作用?为什么我们需要“patch”? “patch”和内核(即特征检测器)之间有什么关系?
在CNN学习训练过程中,不是一次来处理一整张图片,而是先将图片划分为多个小的块,内核 kernel (或过滤器或特征检测器)每次只查看图像的一个块,这一个小块就称为 patch,然后过滤器移动到图像的另一个patch,以此类推。
当将CNN过滤器应用到图像时,它会一次查看一个 patch 。
CNN内核/过滤器一次只处理一个 patch,而不是整个图像。这是因为我们希望过滤器处理图像的小块以便检测特征(边缘等)。这也有一个很好的正则化属性,因为我们估计的参数数量较少,而且这些参数必须在每个图像的许多区域以及所有其他训练图像的许多区域都是“好”的。
所以 patch 就是内核 kernel 的输入。这时内核的大小便是 patch 的大小。(不能保证这个结论是正确的)
https://blog.csdn.net/wills798/article/details/97974617
一个有关图像的更全面的资料。
目前,因为项目需要,需要简单地对机器学习相关的概念有一个初步了解,故总结记录在这里,其中,主要参考了这一系列文章: https://scruel.gitee.io/ml-andrewng-notes/week2.html
两种定义(正式或非正式: 下棋,过滤垃圾邮件)
监督学习
和无监督学习
,区别在于是否需要人工参与数据结果的标注。
监督学习(Supervised Learning):有反馈。给予计算机一定的输入和对应的结果(训练集),建模拟合,让计算机推测结果。
回归问题就是预测一系列的连续值;比如,根据照片推测年龄。
分类问题就是预测一系列的离散值。判别类的一些应用就是该类型。这里提了一下支持向量机。
这里的训练集没有标记结果,即计算机执行完毕后不知道最后的结果的成功率。分为几个簇,也叫聚类算法。一般有两种:
计算整个训练集所有损失函数之和的平均值。
计算单个样本的误差。
解决在特征值很大的情况下,引入梯度下降的概念,让计算机自动找出最小化代价函数时对应的塞塔值。
这部分就和高等数学紧密相连了,感觉有些难度,暂时搁浅。 https://scruel.gitee.io/ml-andrewng-notes/week1.html
逻辑回归(Logistic Regression)
分类问题往往是判别的一种,预测的结果是离散值,逻辑回归算法就是被用于解决这类分类问题。
以肿瘤诊断为例,是一个二元分类问题(Binary class problems),则 y $\in$ {0,1}, 0表示负向类(negative class),1为正向类(postive class)
为了使值分布在(0,1), 引入逻辑回归模型。
简单来说,决策边界就是分类的分界线。
关于拟合的表现,可以分为三类问题:
欠拟合(Underfitting) 无法很好的拟合训练集中的数据,预测值和实际值的误差很大,这类情况被称为欠拟合。拟合模型比较简单(特征选少了)时易出现这类情况。类似于,你上课不好好听,啥都不会,下课也差不多啥都不会。
优良的拟合(Just right) 不论是训练集数据还是不在训练集中的预测数据,都能给出较为正确的结果。类似于,学霸学神!
过拟合(Overfitting) 能很好甚至完美拟合训练集中的数据,即趋向于0 ,但是对于不在训练集中的新数据,预测值和实际值的误差会很大,泛化能力弱,这类情况被称为过拟合。拟合模型过于复杂(特征选多了)时易出现这类情况。类似于,你上课跟着老师做题都会都听懂了,下课遇到新题就懵了不会拓展。
为了度量拟合表现,引入:
偏差(bias)
方差(Variance)
避免过拟合的方法有:
减少特征的数量
1. 手动选取需保留的特征
2. 使用模型选择算法来选取合适的特征(如 PCA 算法)
3. 减少特征的方式易丢失有用的特征信息
正则化(Regularization)
1. 可保留所有参数(许多有用的特征都能轻微影响结果)
2. 减少/惩罚各参数大小(magnitude),以减轻各参数对模型的影响程度
3. 当有很多参数对于模型只有轻微影响时,正则化方法的表现很好
很多时候由于特征数量过多,过拟合时我们很难选出要保留的特征,这时候应用正则化方法则是很好的选择。
那么类比一下,把上图中的细胞核(nucleus)类比成工人,轴突(axon)类比传送带,树突(dendrite)则比类比成工人的双眼。一个又一个细胞体,从树突接收需要处理的信息,对其进行处理后,再经由轴突通过电信号把处理完的信息传递出去,直到理解信息的内容。当然啦,我们大脑的实际上还要更为复杂,而且一个人的神经元数目就比地球上所有流水线的工人之和还要多呢~
人工神经网络中,树突对应输入(input),细胞核对应激活单元(activation unit),轴突对应输出(output)。
我们一般把神经网络划分为三部分(注意,不是只有三层!),即输入层(input layer),隐藏层(hidden layer)和输出层(output layer)。
图中的一个圈表示神经网络中的一个激活单元,输入层对应输入单元,隐藏层对应中间单元,输出层则对应输出单元。中间激活单元应用激活函数(activation_function)处理数据。
这篇文章重点记录二叉树的一些不入流的题目,但是很有意思。
题目的大意是给你一个二叉树,然后输出它的遍历字符串,就比如;
Input: Binary tree: [1,2,3,4]
1
/ \
2 3
/
4
Output: "1(2(4))(3)"
Explanation: Originallay it needs to be "1(2(4)())(3()())",
but you need to omit all the unnecessary empty parenthesis pairs.
And it will be "1(2(4))(3)".
Input: Binary tree: [1,2,3,null,4]
1
/ \
2 3
\
4
Output: "1(2()(4))(3)"
Explanation: Almost the same as the first example,
except we can't omit the first parenthesis pair to break the one-to-one mapping relationship between the input and the output.
这个题目有意思在,有一点 tip 在里面,也就是需要在你写程序之前进行一些观察。看着那些括号和数字是一些杂乱无章的符号,实际有固定套路的。
通过第二个例子,假设根节点有右子节点,而没有左子节点的话,需要在根节点后面添加一个”()”,当然这个”()”你也可以看成一个空节点。此时,一般还是看不出的, 这时候,你把output的首位和末尾分别用”()”进行包裹起来,则这个结果就有规律了。
class Solution {
public:
string tree2str(TreeNode* t) {
string res = "";
if(!t) return res;
tree2str_helper(t, res);
return string(res.begin()+1, res.end()-1);
}
private:
void tree2str_helper(TreeNode* t, string& res){
if (!t) return;
res += "(";
if (t) res += to_string(t->val);
if(!t->left && t->right) res += "()";
tree2str_helper(t->left, res);
tree2str_helper(t->right, res);
res +=")"; // 这个语句为什么放在这里,把我搞蒙了
}
};