Redis 使用字符串对象来表示位数组,因为字符串对象使用的 SDS 数据结构是二进制安全的,所以程序可以直接使用 SDS 结构来保存位数组,并使用 SDS 结构的操作函数来处理位数组。
在 SDS 结构当中,buf
字节数组除了字符串结尾的 \0
空字符,其余的位置都存储着一个字节长的位数组,一个字节可以存储 8 位的二进制。
这里需要注意的是,在 buf
数组中存储的二进制位数组的顺序与实际书写的顺序相反,比如 01010101
存储在 buf
数组中的结构是 10101010
这样的倒序,使用逆序来保存位数组可以简化 SETBIT
的实现。
Redis 提供了 GETBIT
、SETBIT
、BITCOUNT
、BITOP
、BITPOS
、BITFIELD
、BITFIELD_RO
等命令用于处理二进制位数组。
GETBIT <bitarray> <offset>
命令用于返回位数组 bitarray
在 offset
偏移量上的二进制位的值。其详细执行过程如下:
byte = offset / 8
得到 offset
偏移量指定的二进制位保存在位数组的哪个字节;bit = (offset mod 8) + 1
得到 offset
偏移量指定的二进制位是 byte
字节的第几个二进制位;byte
值和 bit
值,在位数组 bitarray
中定位 offset
偏移量指定的二进制位,并返回这个位的值。SETBIT <bitarray> <offset> <value>
可以看作是 GETBIT
的反向操作,只是需要注意设置二进制位时有可能需要扩展 buf
数组的长度。
具体的执行过程如下:
len = (offset / 8) + 1
得到保存 offset
偏移量指定的二进制位需要多少字节;bitarray
位数组的长度是否满足要求,否则需要对 SDS 的进行扩展,并且将新增的二进制位全部置为 0;byte = offset / 8
得到 offset
偏移量指定的二进制位保存在位数组的哪个字节;bit = (offset mod 8) + 1
得到 offset
偏移量指定的二进制位是 byte
字节的第几个二进制位;byte
值和 bit
值,在位数组 bitarray
中定位 offset
偏移量指定的二进制位,首先将这个位现在的值保存在 oldvalue
变量中,然后将新值 value
设置为这个二进制位的值;oldvalue
的值。由于 buf
数组使用逆序保存位数组,当 Redis 对 buf
数组进行扩展之后,写入操作都可以直接在新扩展的二进制位中完成,而不必改动位数组原来已有的二进制位。
BITCOUNT key [start] [end]
命令用于统计给定位数组中,值为 1 的二进制位的数量。
BITOP operation destkey key [key ...]
支持对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。operation
可以是 AND
、 OR
、 NOT
、 XOR
这四种操作中的任意一种:
AND
: 逻辑与OR
: 逻辑或NOT
: 逻辑非XOR
: 逻辑异或因为 BITOP AND
、BITOP OR
、BITOP XOR
三个命令可以接受多个位数组作为输入,程序需要遍历输入的每个位数组的每个字节来进行计算,所以这些命令的复杂度为 \(O(n^2)\);与此相反,因为 BITOP NOT
命令只接受一个位数组输入,所以它的复杂度为 \(O(n)\)。
BITPOS key bit [start [end [BYTE | BIT]]]
返回字符串中设置为 1 或 0 的第一个位的位置。
默认情况下,整个字符串都会被检索一遍。命令的
使用 start
和 end
参数默认可以指定一个字节的范围,在 7.0.0 版本之后,提供了 BYTE
和 BIT
指定以字节为范围还是位为范围。
BITCOUNT
命令要做的工作初看上去并不复杂,但实际上要高效地实现这个命令并不容易,需要用到一些精巧的算法。
实现 BITCOUNT
命令最简单直接的方法,就是遍历位数组中的每个二进制位,并在遇到值为 1 的二进制位时,将计数器的值增一。
遍历算法虽然实现起来简单,但效率非常低,因为这个算法在每次循环中只能检查一个二进制位的值是否为 1,所以检查操作执行的次数将与位数组包含的二进制位的数量成正比。
查表算法就是创建一个表,表的键为某种排列的位数组,而表的值则是相应位数组中值为 1 的二进制位的数量。
创建了这种表之后,就可以根据输入的位数组进行查表,在无须对位数组的每个位进行检查的情况下,直接知道这个位数组包含了多少个值为 1 的二进制位。
初看起来,只要创建一个足够大的表,那么统计工作就可以轻易地完成,但这个问题实际上并没有那么简单,因为查表法的实际效果会受到内存和缓存两方面因素的限制:
BITCOUNT
命令要解决统计一个位数组中非 0 二进制位的数量的问题,在数学上被称为“计算汉明重量(Hamming Weight)”。目前已知效率最好的通用算法为 variable-precision SWAR 算法,该算法通过一系列位移和位运算操作,可以在常数时间内计算多个字节的汉明重量,并且不需要使用任何额外的内存。
以下是一个处理 32 位长度位数组的 variable-precision SWAR 算法的实现:
uint32_t swar(uint32_t i){
i = (i & 0x55555555) + ((i>>1) & 0x55555555); // 步骤 1
i = (i & 0x33333333) + ((i>>2) & 0x33333333); // 步骤 2
i = (i & 0x0F0F0F0F) + ((i>>4) & 0x0F0F0F0F); // 步骤 3
i = (i - 0x01010101) >> 24; // 步骤 4
return i;
}
variable-precision SWAR 算法实质上是通过分而治之的思想,将计算拆解成多个小问题去解决:
01010101010101010101010101010101
做逻辑与操作,并且右移 1 位之后继续做逻辑与操作,最终取它们的和。这一步的想法是将 32 位拆成每 2 位作为一个组合,统计出每一组中 1 的个数;00110011001100110011001100110011
做逻辑与操作。这一步的想法就是拆成每 4 位作为一个组合,统计出每一组中 1 的个数;00001111000011110000111100001111
做逻辑与操作。这一步的想法就是拆成每 8 位作为一个组合,统计出每一组中 1 的个数;i - (0x01010101)
计算出汉明重量并记录在二进制的高八位,>> 24
语句则通过右移运算,将汉明重量移到最低八位,最后二进制对应的十进制就是汉明重量。因为 variable-precision SWAR 算法是一个常数复杂度的操作,所以可以按照自己的需要,在一次循环中多次执行 variable-precision SWAR 算法,从而按倍数提升计算汉明重量的效率。
当然,在一个循环里执行多个 variable-precision SWAR 算法调用这种优化方式是有极限的:一旦循环中处理的位数组的大小超过了缓存的大小,这种优化的效果就会降低并最终消失。
BITCOUNT
命令的实现用到了查表和 variable-precision SWAR 两种算法:
实际上 BITCOUNT
命令实现的算法复杂度为 \(O(n)\),其中 n 为输入二进制位的数量。
首发于「程序员翔仔」,点击查看更多。
前言我在全新项目中用过androidx,也做过老项目迁移到androidx,所以,我想表达的是androidx其实没那么神秘,也没那么多坑,时至今日也一年多过去了,基本趋于稳定,未来也是大势所趋,所以,迁移是迟早的事。何为androidxandroidx其实是对SupportLibrary的一次整合升级,即我们常用的v4包、v7包等,这些包最开始是做向下兼容的,但是现如今向下兼容的版本(targetSdkVersion)已经太低了,比如7、9、13等,现在都是android4.4版本19起步了,所以向下兼容已经需要了,不可能还有适配android2.3的,而且还加了很多新东西,比如v7包还加入了recyclerview,所以基于种种,官方来了一次整合升级,并且以后的重心也在androidx上,v4v7慢慢也会不维护了。开始迁移Refactor>MigratetoAndroidX 迁移之前会提示备份,默认勾选,看自己需求。然后就是修改命名包名什么的,因为以前是android.support.*下面的,迁移之后变成androidx.*。support包有的,androidx也都有。
相信任何一位朋友都对28法则不会陌生吧,由此黄金法则所带来的影响也是极其正常深远的。因此,在整个站长圈中,我们不难看出真正能够赢利的其实只有其中的百分之二十的人,甚至可能连百分之二十这个数字都不一定能够达到。从网络刚刚开始兴起之时,直到今时今日所有的站长都未曾有一刻放弃过,试图在网上寻找到一条切实可行的赚钱之路。无数的站长朋友们都在重复不断的问着同样的问题。做什么样的网站最赚钱啊?网站要是有流量了,可以赚多少钱啊?比如一万IP能赚多少?网站要怎么样,才能有排名啊?每当我被学员们问到这些问题的时候,我也会由衷的发出一句感叹:曾几何时,我也曾如同你们的一样,痴痴傻傻的问过这些同样的问题。不得不说对于新人站长来说,以上这些问题确确实实是他们最为关心的几个问题,也是最为困扰他们的几个问题,可以说如果这几个问题没有得到很好的处理的话,那么他们将注定会失败。所以在这里我给新人站长们建站的选择性建议:新人站长首个网站目标应尽量选低。相信这一点对于各位老站长来说是深有体会的,大网站想要得到发展是很难的,但是相对来说小站就要容易得多了。这里所提到的“小”,并不是指的网站的规模小的意思,而应当是指网站的内
背景 之前在进行多服务器配置负载均衡时; 注意到会出现Session会话(一般用于用户登录信息保存)无法使用的情况; 而成熟的开发者都是建议使用缓存中间件,如redis/memcache 尤以Redis+Session推荐之多 此处做一下在ThinkPHP5框架下的配置操作… 环境 ThinkPHP版本: ThinkPHP5.1.40 操作系统: Linux/windows10复制配置前提当然是有可供使用的Redis服务器(建议配置为Redis集群,冗余保证访问正常) 首先保证Redis服务的正常启动,可访问 2.然后,是要配置redis扩展(网上一找一大把) 3.直接打开配置文件:"config/session.php",补充如下配置信息: 'type'=>'redis',//驱动方式 'host'=>'127.0.0.1',//redis主机 'port'=>6379,//redis端口 //'password'=>&
Linux内核对网络包的接收过程大致可以分为接收到RingBuffer、硬中断处理、ksoftirqd软中断处理几个过程。其中在ksoftirqd软中断处理中,把数据包从RingBuffer中摘下来,送到协议栈的处理,再之后送到用户进程socket的接收队列中。图1Linux内核接收网络包过程理解了Linux工作原理之后,还有更重要的两件事情。第一是动手监控,会实际查看网络包接收的整体情况。第二是调优,当你的服务器有问题的时候,你能找到瓶颈所在,并会利用内核开放的参数进行调节。一先说几个工具在正式内容开始之前,我们先来了解几个Linux下监控网卡时可用的工具。 1)ethtool首先第一个工具就是我们在上文中提到的ethtool,它用来查看和设置网卡参数。这个工具其实本身只是提供几个通用接口,真正的实现是都是在网卡驱动中的。正因为该工具是由驱动直接实现的,所以个人觉得它最重要。该命令比较复杂,我们选几个今天能用到的说-i显示网卡驱动的信息,如驱动的名称、版本等-S查看网卡收发包的统计情况-g/-G查看或者修改RingBuffer的大小-l/-L查看或者修改网卡队列数-c/-C查看或者修
关键字:javaweb开发框架正文|内容介绍一个简单易用的JavaWeb应用开发框架,包含MVC、IoC、事件通知、ORM、插件等组件。在实体模型上使用JSON贯穿前后端,使应用开发更加快捷。这是Latke不同于其他框架的地方,比较适合小型应用的快速开发。软件架构基于java8以上版本基于springboot模块开发使用说明基于java8以上版本开发用eclipse/idea打开源文件(一般idea会自动提示需要安装的插件或者模块)导入工程直接运行即可02—【下载地址】https://gitee.com/dl88250/latke.git03 —最近疫情期,自己憋在家里除了日常的活动外,没有其它事情要做,感觉时间都浪费掉了。同时由于疫情经济和情感上压力也有些大。为了排解压力让自己充实起来,我决定自己用一个月的时候自学一个新语言,选来选去决定学习python。在学习的过程中接有时感觉特别累,每天总体上也坚持自学至少三个小时。学习中发现了一个比较好的软件xmind,通过xmind这个思维导图软件制作了一些自学笔记,把每节的重点整理成图形的方式,很容易直观理解和掌握。最近整理出来一些图例分享
1.DNS服务原理DNS是域名系统(DomainNameSystem)的缩写,它是由解析器和域名服务器组成的。域名服务器是指保存有该网络中所有主机的域名和对应IP地址,并具有将域名转换为IP地址功能的服务器。其中域名必须对应一个IP地址,而IP地址不一定有域名。域名系统采用类似目录树的等级结构。域名服务器为客户机/服务器模式中的服务器方,它主要有两种形式:主服务器和转发服务器。将域名映射为IP地址的过程就称为“域名解析”。在Internet上域名与IP地址之间是一对一(或者多对一)的,域名虽然便于人们记忆,但机器之间只能互相认识IP地址,它们之间的转换工作称为域名解析,域名解析需要由专门的域名解析服务器来完成,DNS就是进行域名解析的服务器。DNS命名用于Internet等TCP/IP 网络中,通过用户友好的名称查找计算机和服务。当用户在应用程序中输入DNS名称时,DNS服务可以将此名称解析为与之相关的其他信息,如IP地址。因为,你在上网时输入的网址,是通过域名解析系统解析找到了相对应的IP地址,这样才能上网。其实,域名的最终指向是IP。通常情况下我们之用到了DNS服务器的正向解析功能
Here文档here文档,又称作heredoc、hereis、here-字串或here-脚本,是一种在命令行shell(如sh、csh、ksh、bash、PowerShell和zsh)和程序语言(像Perl、PHP、Python和Ruby)里定义一个字串的方法。它可以保存文字里面的换行或是缩排等空白字元。一些语言允许在字串里执行变量替换和命令替换。 here文档最通用的语法是<<紧跟一个标识符,从下一行开始是想要引用的文字,然后再在单独的一行用相同的标识符关闭。在Unixshell里,here文档通常用于给命令提供输入内容。shell在以下几个例子中,文字用here文档传递给tr命令。$tra-zA-Z<<END_TEXT >onetwothree >unodostres >END_TEXT ONETWOTHREE UNODOSTRES复制END_TEXT被用作标识符。它指定了here文档的开始和结束ONETWOTHREE和UNODOSTRES是执行后tr的输出。在<<后面添加一个减号,可以使TAB字元被忽略。这允许在shell脚本
话聊 建设数仓ETL 工具 面临的问题分层 分层的出发点 分层设计模型建设 为什么要建设模型 怎么建设模型 理清工作思路 实施步骤 建模方法及实施规范建设 临时表管理 代码规范 流程规范 话聊技术升级快于我们的想象,今天的故事在明天来看就是一种常识。对于数仓而言,又何尝不是?互联网的发展,导致大数据的人才缺口。互联网公司雨后春笋,传统行业机巧转身。短短几年,数据行业已沧海桑田。今天谈大数据已不复当年雾里看花的景象,它像一列更高速的快车,和老前辈们一样,向自己的终点加速。回到主题,最近负责一个数据中台项目的建设,从0到1的建立数仓。模型建设,参考维度模型的方式。通过维度+事实,支持业务数据需求。走了不少弯路,在这里总结总结,更希望和大家交流。建设数仓什么是数仓,为什么建设数仓,怎么建设数仓?(我是谁,我从哪里来,我到哪里去) Inmon将数据仓库定义为:在企业管理和决策中面向主题的、集成的、与时间相关的、不可修改的数据集合。数据仓库的目标:数据资产、决策信息。系统层面etl过程:打通你的任督二脉(离线+实时),让数据在整个环节中流通起来数据分层:一套(低耦合、高内聚)的层级,是十分重要
TypeScript不是一个高深的技术,它不过是一个javascript的超集,那么什么是超集呢?所谓的超集其实就是最终将你写的TypeScript编译成javascript去执行,因为浏览器上能跑的脚本语言是javascript,这个本质要搞清楚传统的Javascript缺点:1.弱类型,不严谨无法在编写时察觉出同一个变量的类型是否保持一致比如:vara=1 //如果这个b的值是“1”,字符串 varb="1" console.log(a+b)复制结果:2.不依赖插件,无法感知编码书写是否出现边际错误(出现某一瞬间空值等)特别是ES6之前存在全局变量,var会给全局状态下添加属性以及污染全局加上ES5的变量提升作用域等混合情况,很容易导致变量查找时出现undefined的问题,但是这个问题需要代码运行才能报错例如:vara; functiontest(){ a=1 } console.log(a)//undefined console.log(window.a)//undefined ------------------- vara; funct
BBR是Google开源的TCPBBR拥塞控制算法,并提交到了Linux内核,最新的4.10版内核已经用上了该算法。 主要用于网络加速,类似于锐速。不支持OpenVZ的机器。本脚本适用环境系统支持:CentOS6+,Debian7+,Ubuntu12+虚拟技术:OpenVZ以外的(KVM、Xen、VMware等)内存要求:≥128M日期:2017年02月22日关于本脚本本脚本已在Vultr上的VPS全部测试通过。当脚本检测到VPS的虚拟方式为OpenVZ时,会提示错误,并自动退出安装。某些服务商(如DigitalOcean)可能需要首先将VPS配置为可自定义内核,然后grub2的配置才会生效。脚本运行完重启发现开不了机的,打开VPS后台控制面板的VNC,开机卡在grub引导,手动选择内核即可。由于是使用最新版系统内核,最好请勿在生产环境安装,以免产生不可预测之后果。使用方法使用root用户登录,运行以下命令:wget --no-check-certificate https://github.com/teddysun/across/raw/master/bbr.shchmod +x b
掌网科技携手中国联通布局5G智能终端VR,计划入驻3000家门店 2018世界移动大会期间,中国联通发布打造极致用户体验为目标的5G及网络转型重大战略,并表示将积极营造5G产业合作新生态。近日,联通多家线下门店首现VR体验项目。据了解,该项目是掌网科技推出的面向5G智能终端VR的娱乐应用项目,使用面向5G技术升级的星轮VIULUX-VR头显让人们享受更流畅的VR体验。VRPinea独家点评:重磅消息,5G要来带VR好好玩一把啦!DPVR观影VR一体机首发24小时销量突破1200台8月8日0点,大朋DPVR全景声巨幕影院于京东、天猫、3D播播同步开启预售,据称在24小时内销量突破1200台。大朋巨幕影院有“典雅白”和“尊贵黑”两种颜色,同时“潮人红”和“玫瑰金”配色也即将发售。此外,预订即送500元观影大礼包(含64GTF卡和1年迅雷超级会员等福利)活动将会持续到8月15日——新品正式开售之日,折算下来到手价格仅为899元。VRPinea独家点评:活动期间真的很划算哦~《YoungBlood》报告:英国一半青年人仍认为VR会让人更加孤立品牌体验机构Amplify日前公布了第二份《Youn
众所周知,验证码的出现是为了区分人和机器,但随着科技的发展,黑产从业者的可图之利增多,验证码的战场也进入了一段破解与抗破解的持久博弈。验证码在逐渐复杂的同时,黑灰产的攻击手段也不断提升。本文就从验证码与打码平台的对抗讲起。何为打码平台?打码平台的基本原理是利用人工智能技术实现对验证码设计原理的突破。其工作流程如下图所示:以前黑灰产要想获取数据,首先会向自己想要获取的数据页面发送请求,若该数据页面没有任何对于黑灰产的防护机制的话,那么黑灰产轻而易举的就能获取到数据;反之如果该数据页面存在验证码防御机制,那么在黑灰产获取数据的时候不会直接就返回数据,而是先弹出一个验证码作为人机验证的条件,只有通过了这个验证码的识别才返回数据。对于一般的黑灰产而言,其是没有应对验证码手段的,于是就获取不到数据。打码平台的出现则解决了这一问题。黑灰产把获取到的验证码相关信息提交至打码平台,打码平台负责破解验证码,然后把正确的验证结果返回给黑灰产,让黑灰产在带着正确的验证结果去请求数据页面,大大加大了验证码被破解的风险。综上,原本的请求流程只有黑灰产和数据页面的双向通信,由于打码平台的加入,现在这条链路上便演变
前言 本文是我学习JavaScript过程中收集与整理的一些易错知识点,将分别从变量作用域,类型比较,this指向,函数参数,闭包问题及对象拷贝与赋值这6个方面进行由浅入深的介绍和讲解,其中也涉及了一些ES6的知识点。 JavaScript知识点 1.变量作用域 vara=1; functiontest(){ vara=2; console.log(a);//2 } test();复制 上方的函数作用域中声明并赋值了a,且在console之上,所以遵循就近原则输出a等于2。 vara=1; functiontest2(){ console.log(a);//undefined vara=2; } test2(); 复制 上方的函数作用域中虽然声明并赋值了a,但位于console之下,a变量被提升,输出时已声明但尚未被赋值,所以输出“undefined”。 vara=1; functiontest3(){ console.log(a);//1 a=2; } test3(); 复制 上方的函数作用域中a被重新赋值,未被重新声明,且位于console之下,所以输出全局作用域中的a
一、方法定义 是语句的集合,他们在一起执行一个功能。 方法包含于类或是对象中。 在程序中被创建,在其他地方被引用。 一个方法只执行一个功能,原子性,方便后期扩展。 代码: 修饰符返回值类型方法名(参数类型参数名){ 方法体 return返回值; } 复制 二、方法调用 调用方法:对象名.方法名(实参列表) Java支持两种调用方式,根据是否返回值来进行选择。 返回是一个值的时候:intnum=max(23,45); 方法返回值是void,方法调用一定是一条语句:System.out.println("Hello,kuangshen!"); Java都是值传递 三、方法的重载 就是在一个类中,相同的函数名称,但形参不同的函数。 方法重载的规则: 方法名必须相同 参数列表必须不同(个数不同,或是类型不同、参数排序顺序不同等) 方法的返回值可以相同也可以不同 仅仅返回类型不同是不足以成为方法的重载的 方法名称相同时,编译器会根据调用方法的参数个数,参数类型等逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错。 四、命令行传参 有时候希望运行一个程序时候再传递
1、如何使用promise,做到无限then 代码如下 functionreducePromise(promiseArrGen){ promiseArrGen.reduce((pre,next)=>{ returnpre.then((data)=>{ console.log(data); returnnext(data); }) },Promise.resolve(0)) } functioncreatePromise(i){ return()=>{ returnnewPromise((resolve,reject)=>{ setTimeout(()=>{ resolve(i) },1000) }) } } letPromiseArrGens=[] for(vari=1;i<10;i++){ PromiseArrGens.push(createPromise(i)) } reducePromise(PromiseArrGens);复制 reducer的本质是递归,有很沙雕的方法,实现promise无限then letreduceProm
小人见怪不怪,世界上最可怕的就是会技术的小人,防不胜防! sa密码泄露也就算了,关键是人家也可以前台攻击,直接把你弄的没辙! 在诅咒这种小人的同时,除了加强服务器安全管理,密码策略等,SQLServer2008开始,又出现了一个更牛叉的功能:审核。 对外可以优雅地声称,叫防黑客,对内,这技术叫防小人! 这审核功能,无非就是看一下有哪些人试图入侵数据库服务器,入侵了之后是否有drop表,是否有delete数据 开始吧: 1,打开数据库-安全性-审核,右击审核-新建审核 2,修改:审核名称,指定服务器的文件路径,确定,右键-启用审核 3,创建一个testDB(DEMO使用,自己有库的忽略) usemaster; GO IFDATABASEPROPERTYEX('testDB','version')>0 BEGIN ALTERDATABASEtestDBSETSINGLE_USER WITHROLLBACKIMMEDIATE; DROPDATABASEtestDB; END CREATEDATABASEtestDB; GO usetestDB; GO CREATET
题目:(原题是英文而且很迷)求区间内数的LIS长度==k的个数,比如153948的LIS为1348,长度为4。据说这种题叫DP中DP,本来是线性,再套一层状压+数位,简直厉害到不行…… 线性的部分为O(nlogn)的LIS。比如现在找出的序列为1348,两个策略,如果再来一个2就变成1248(二分找第一个比它大的数),再来9就变成12489(更新长度)。代码在下面 1#include<cstdio> 2#include<ctime> 3#include<cstring> 4#include<iostream> 5#include<algorithm> 6usingnamespacestd; 7intn,f[1010],x,l,r,len; 8intmain() 9{ 10scanf("%d",&n); 11f[0]=-1; 12for(inti=1;i<=n;++i){ 13scanf("%d",&x); 14l=1;r=len; 15if(x>f[len]){ 16f[++len]
softmax是logisiticregression在多酚类问题上的推广,\(W=[w_1,w_2,...,w_c]\)为各个类的权重因子,\(b\)为各类的门槛值。不要想象成超平面,否则很难理解,如果理解成每个类的打分函数,则会直观许多。预测时我们把样本分配到得分最高的类。 Notations: \(x\):输入向量,\(d\times1\)列向量,\(d\)是feature数 \(W\):权重矩阵,\(c\timesd\)矩阵,\(c\)是label数 \(b\):每个类对应超平面的偏置组成的向量,\(c\times1\)列向量 \(z=Wx+b\):线性分类器输出,\(c\times1\)列向量 \(\hat{y}\):softmax函数输出,\(c\times1\)列向量 记\(\vec{e}_j=[0,...,1,...,0]^T\in\mathbb{R}^{c\times1}\),其中\(1\)出现在第\(j\)个位置 \(1_c\)表示一个全\(1\)的\(c\)维列向量 \(y\):我们要拟合的目标变量,是一个one-hotvector(只有一个1,其余均为0),也