提升公开讲话自信的三个技巧

“自”信

在进行其他训练之前,每个人都能做到的最简单的事情就是“自”信。

当出现小失误的时候,不要一直“抱歉”、“对不起”说个不停。当感觉大家都没有跟上思维时,不要说“可能大家都没听懂我在说什么”。自己发现问题后,自己把问题解决就好。出现失误,更正即可;表述不清,换种方式重新说清即可。

无论是接连不断的道歉还是反复强调自己没有让大家听懂,都不会帮助你解决问题,更不会帮助你的听众,反而会让你更加紧张或者自我否定,所以在公开讲话时不要这样做,要“自”信。

听众并非时刻注意你的一举一动

当进行公开讲话时,你可能以为听众都会把100%的注意力投入到你身上,以为听众会注意到你说的每一个字,以为听众会注意到你做的每一个动作。事实是,听众更可能会在自己的头脑里构建自己的理解,而忽略了你演讲的细节。

很多对你而言非常明显的细节,对听众而言,甚至会被全部忽略。这也是人们会反复强调重点的原因——为了不让听众错过重点——听众总是在忽略信息。知道了这一点,下次公开讲话时你会更加自信。

训练克服恐惧

正常情况下,每个人从小到大都在讲话,经过这么多年的练习,一个人的语言能力已经足以支撑其自如地讲话。每个人都至少能和某个人自然舒适地讲话,这个人可能是家人、朋友或伴侣,甚至可以是自己。

在公开讲话时不自信,更多的情况是思想没有跟上能力,具体一点就是不相信自己能在压力之下把话讲好。这种压力往往来自于对尴尬的恐惧。让自己多尴尬几次是一种解决办法。

可以这样训练:在一个安全的环境里——比如找上一些志同道合的朋友,大家都是一起进行训练的,所以并不会真的产生实质性损失——让自己处于各种可能出现的尴尬场景之中。可以让“听众”问你一些尖锐的问题;可以让“听众”“强迫”你把话讲明白,把句子说完整;还可以让“听众”在你讲话时打断你,使你不得不在讲话正中间冷场很长一段时间。总之,让“听众”想方设法使你尴尬难堪。多次进行这种训练,日积月累你会发现自己能处理好各种情况,在压力之下也能自信从容地完成自己的公开讲话。

Python PuLP 简单求解线性规划问题

一般步骤

  1. 导入 PuLP
  2. 使用 LpProblem 定义问题(名称、类型)
  3. 使用 LpVariable 定义变量(名称、下限、上限、类型)
  4. 添加目标表达式
  5. 添加约束条件
  6. 求解
  7. 输出结果

简单实例

问题

要用最低成本生产一种猫粮,同时使这种猫粮的营养成分满足一定的要求。生产者希望通过改变每种原料的添加量来实现这一目标。

每份猫粮为100克,其营养成分要求为:蛋白质不少于8克,脂肪不少于6克,纤维不多于2克,盐不多于0.4克。

猫粮的主要原料和其每克成本为:鸡肉($0.013)、牛肉($0.008)、羊肉($0.010)、大米($0.002)、小麦($0.005)、凝胶($0.001)。

每克原料对最终猫粮的营养贡献如下表所示:

原料蛋白质脂肪纤维
鸡肉0.1000.0800.0010.002
牛肉0.2000.1000.0050.005
羊肉0.1500.1100.0030.007
大米0.0000.0100.1000.002
小麦0.0400.0100.1500.008
凝胶0.0000.0000.0000.000
每克原料对最终猫粮的营养贡献,以克为单位。

求成本最低的原料添加量方案。

简化版问题

先考虑简化后的问题,假设只有鸡肉和牛肉两种原料。原料的添加量不能为负值。

简化版问题求解

导入 PuLP

from pulp import *

使用 LpProblem 定义问题

prob = LpProblem("The Cat Food Problem", LpMinimize)

LpProblem 第一个参数为问题的名称,可自定义。第二个参数为问题类型,可在 LpMinimizeLpMaximize 中选择。本题求成本最小值。

使用 LpVariable 定义变量

x1 = LpVariable("ChickenPercent", 0, None, LpContinuous)
x2 = LpVariable("BeefPercent", 0)

LpVariable 第一个参数为变量的名称,可自定义。第二个参数为变量的下限,本题为 0。第三个参数为变量的上限,None 在上下限处表示正无穷或负无穷。第四个参数为变量的类型,可选的值有 LpContinuous, LpIntegerLpBinary,意思即为字面意思,默认为 LpContinuous

添加目标表达式

prob += 0.013 * x1 + 0.008 * x2, "Cost per can"

"Cost per can" 为标识符,可自定义也可省略。注意使用 += 而不是 =

添加约束条件

prob += x1 + x2 == 100, "PercentSum"
prob += 0.100 * x1 + 0.200 * x2 >= 8.0, "Protein"
prob += 0.080 * x1 + 0.100 * x2 >= 6.0, "Fat"
prob += 0.001 * x1 + 0.005 * x2 <= 2.0, "Fibre"
prob += 0.002 * x1 + 0.005 * x2 <= 0.4, "Salt"

同样,引号中的内容为标识符,可自定义也可直接省略整个引号。注意使用 += 而不是 =

求解

prob.solve()

使用默认求解器进行求解。

输出结果

print("Status:", LpStatus[prob.status])
for v in prob.variables():
    print(v.name, "=", v.varValue)
print("Cost per can = ", value(prob.objective))

prob.status 是求解的状态,为整数型,有 LpStatusOptimal LpStatusNotSolved, LpStatusInfeasible, LpStatusUnboundedLpStatusUndefined 这四种返回,意思即为字面意思。该值是整数型,可以通过 LpStatus[prob.status] 来获取字符串类型的状态。

prob.objective 是求解后目标表达式的值,在本题中即为所求的最低成本。

完整问题求解

求解的基本步骤是一样的,不过在使用 LpVariable 定义变量、添加目标表达式和添加约束条件时可以使用一些方法来减少需要编写的代码。

导入 PuLP

from pulp import *

定义问题中的数据

Ingredients = ["CHICKEN", "BEEF", "MUTTON", "RICE", "WHEAT", "GEL"]

costs = {
    "CHICKEN": 0.013,
    "BEEF": 0.008,
    "MUTTON": 0.010,
    "RICE": 0.002,
    "WHEAT": 0.005,
    "GEL": 0.001,
}

proteinPercent = {
    "CHICKEN": 0.100,
    "BEEF": 0.200,
    "MUTTON": 0.150,
    "RICE": 0.000,
    "WHEAT": 0.040,
    "GEL": 0.000,
}

fatPercent = {
    "CHICKEN": 0.080,
    "BEEF": 0.100,
    "MUTTON": 0.110,
    "RICE": 0.010,
    "WHEAT": 0.010,
    "GEL": 0.000,
}

fibrePercent = {
    "CHICKEN": 0.001,
    "BEEF": 0.005,
    "MUTTON": 0.003,
    "RICE": 0.100,
    "WHEAT": 0.150,
    "GEL": 0.000,
}

saltPercent = {
    "CHICKEN": 0.002,
    "BEEF": 0.005,
    "MUTTON": 0.007,
    "RICE": 0.002,
    "WHEAT": 0.008,
    "GEL": 0.000,
}

为了简化后续所需编写的代码,在此把问题中需要使用的数据先进行定义。

使用 LpProblem 定义问题

prob = LpProblem("The Cat Food Problem", LpMinimize)

使用 LpVariable 定义变量

ingredient_vars = LpVariable.dicts("Ingredients", Ingredients, 0)

在这里我们直接使用先前定义的 Ingredients 列表来定义变量。

添加目标表达式

prob += (
    lpSum([costs[i] * ingredient_vars[i] for i in Ingredients]),
    "Cost per can",
)

同样,在这里我们直接使用先前定义的 costs, ingredient_vars, Ingredients 来定义变量。

其中,lpSum 会把其参数列表的各项相加。

添加约束条件

prob += lpSum([ingredient_vars[i] for i in Ingredients]) == 100, "PercentSum"
prob += (
    lpSum([proteinPercent[i] * ingredient_vars[i] for i in Ingredients]) >= 8.0,
    "Protein",
)
prob += (
    lpSum([fatPercent[i] * ingredient_vars[i] for i in Ingredients]) >= 6.0,
    "Fat",
)
prob += (
    lpSum([fibrePercent[i] * ingredient_vars[i] for i in Ingredients]) <= 2.0,
    "Fibre",
)
prob += (
    lpSum([saltPercent[i] * ingredient_vars[i] for i in Ingredients]) <= 0.4,
    "Salt",
)

同上,使用预先定义的数据来简化代码。

求解

prob.solve()

输出结果

print("Status:", LpStatus[prob.status])
for v in prob.variables():
    print(v.name, "=", v.varValue)
print("Cost per can = ", value(prob.objective))

参考资料

Optimization with PuLP(外部链接)

为移动硬盘禁用 UAS

使用 UAS 可能导致 smartmontools 等工具无法正常工作。可以通过编辑 GRUB 配置给内核传递参数,为某一特定设备禁用 UAS。

例如,编辑 /etc/grub.d/10_linux 文件,在文件首部添加 GRUB_CMDLINE_LINUX="usb_storage.quirks=idVendor:idProduct:u" 这一行配置,将 idVendor 和 idProduct 替换为设备的实际值。

idVendor 和 idProduct 可以通过 dmesg 获得。

比如下面的 dmesg 信息:

usb 2-1: new SuperSpeed USB device number 8 using xhci_hcd
usb 2-1: New USB device found, idVendor=0bc2, idProduct=231a
usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[...]
scsi host4: uas
scsi 4:0:0:0: Direct-Access     VENDOR-NAME               0204 PQ: 0 ANSI: 6
sd 4:0:0:0: Attached scsi generic sg2 type 0
sd 4:0:0:0: [sdc] 1953525168 512-byte logical blocks: (1.00 TB/932 GiB)
sd 4:0:0:0: [sdc] 4096-byte physical blocks
sd 4:0:0:0: [sdc] Write Protect is off
sd 4:0:0:0: [sdc] Mode Sense: 53 00 00 08
sd 4:0:0:0: [sdc] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
 sdc: sdc1 sdc2
sd 4:0:0:0: [sdc] Attached SCSI disk

从中我们可以得到 idVendor 为 0bc2idProduct 为 231a

编辑完 GRUB 配置文件,运行 update-grub 使配置生效。重启后,即可为 idVendor:idProduct 设备禁用 UAS。

网站使用 CDN 之后获取访客原 IP 的方法

网络上大多数教程给出的方法都是通过修改程序代码,直接取 X-Forwarded-For 等请求标头的值替换原来 REMOTE_ADDR 变量的值作为原 IP,这种做法有很大的安全隐患,我认为不值得提倡。

安全隐患

根据 RFC 3875 文件,REMOTE_ADDR 变量的值必须为发送请求到服务器的客户端的网络地址。在实践中 REMOTE_ADDR 变量的值往往由服务器直接设置为发送请求的客户端网络地址,而不是由客户端提供,因此其真实性有保证。

与 REMOTE_ADDR 变量不同,X-Forwarded-For 请求标头的值不是由服务器直接决定,而可以由客户端自行设置,实践中一般由代理服务器在转发请求时设置。因为 X-Forwarded-For 请求标头的值可能被客户端伪造,所以不应该轻易相信其真实性。

由于 REMOTE_ADDR 变量的值和 X-Forwarded-For 请求标头的值具有不同的可信度,使用低可信度 X-Forwarded-For 请求标头的值去替换高可信度 REMOTE_ADDR 变量的值便会产生不可忽视的安全隐患。比如,攻击者可以通过伪造 X-Forwarded-For 请求标头来绕过基于 IP 的频率限制、访问控制。更进一步,攻击者还可以构造具有危害性 X-Forwarded-For 请求标头来对服务器进行多种攻击,例如注入恶意代码进行 XSS 攻击就是一种可能的行为。

正确做法

在使用 X-Forwarded-For 请求标头的值之前应该确保其内容可信。因为 X-Forwarded-For 请求标头一般由代理服务器添加,所以至少应该先确认请求来自可信的代理服务器才可使用 X-Forwarded-For 标头的值。

对于使用 CDN 的网站,如果服务器是 nginx,那么在 ngx_http_realip_module 模块的帮助下这一过程将会十分简单。只需编辑相应的 nginx 配置文件,在其中的 http、server 或 location 段,使用 set_real_ip_from 指定可信代理服务器地址(即 CDN 节点的地址),然后使用 real_ip_header 指明一个请求标头(即 X-Forwarded-For 标头),保存并重载 nginx 使配置生效。这样 nginx 收到请求后会检查请求的 REMOTE_ADDR 是否与 set_real_ip_from 相符,如果相符,nginx 会用 real_ip_header 对应标头的值替换 REMOTE_ADDR 原有的值,后端程序只需要正常使用 REMOTE_ADDR 的值即可。这种做法一般不需要改变后端程序。

参考资料

解决 MP4 视频无法在 iPhone 手机播放的问题

本文适用于解决因视频编码导致无法播放的问题。

前言

使用 iPhone、iPad 等苹果设备时会发现有的 MP4 格式视频可以正常播放,而有的却无法播放,在部分 Android 设备上也存在类似问题。大部分情况下,这类无法播放的问题都是因为缺少对应视频编码的解码器造成的,要解决这类问题,一种方法是下载能够解码该视频的播放器,另一种方法是对视频转码。本文介绍后者,即如何对视频进行转码使其能被大多数设备播放。

如果去搜索格式转换、视频转码等内容,会找到各类视频处理工具,其中大部分都需要付费或者含有许多广告。实际上,很多视频问题使用 FFmpeg 就能解决问题,这款免费、开源且无广告的工具也能通过转码解决 MP4 无法在苹果手机播放的问题。

下载 FFmpeg

如果你的电脑上还没有 FFmpeg 程序,你可以前往 FFmpeg 官网(外部链接)下载最新版本的 FFmpeg 程序。

对于 Windows 用户,我在这里提供了一份副本,可以直接下载适用于 64 位操作系统的 FFmpeg n5.0 压缩包(ZIP,103.8 MiB),解压后即可使用命令行调用程序。

对于 Linux 用户,大多数 Linux 发行版的软件仓库中都包含了 FFmpeg 程序,可以直接使用包管理器安装。例如 Debian 和 Ubuntu 用户可直接使用 apt-get install ffmpeg 命令安装 FFmpeg 程序。

执行命令进行转码

使用 FFmpeg 对视频转码,让视频获得最好的兼容性,只用把下面命令中的 <input> 替换为需要转换的视频文件名,然后执行即可:

ffmpeg -i <input> -c:v libx264 -crf 23 -profile:v baseline -level 3.0 -pix_fmt yuv420p -c:a aac -ac 2 -b:a 128k -movflags faststart ksk-example.mp4

得到的 ksk-example.mp4 文件就是转码后生成的能够被大多数设备(包括使用 iOS 的 iPhone 和 iPad 设备)直接正常播放的 MP4 视频。

解释说明

现在问题已经解决。接下来我将进行一些解释说明,如果不感兴趣,可以直接略过。

H.264/AAC 的 MP4 是 HTML5 下兼容性最好的组合。对于没有 H.264 解码器的浏览器,则应该提供 VP9/Vorbis 的 WebM 视频。有这两种组合,基本上就可以兼容目前的所有主流浏览器。对于本文来说, H.264 编码的视频能够在大多数移动设备上正常播放,所以我们采用 H.264 编码。

用 -profile:v baseline -level 3.0 参数可以兼容一些无法处理 H.264 中 CPU 密集型特性的老设备,如果没有这个需求,可以去掉这一参数。

-crf 23 参数影响视频的质量,数值越低质量越好,一般设置在18到28这个区间内即可。如果需要指定视频码率,可以使用类似 b:v 1000k 这样的参数,这么做是因为一些性能不太强劲的设备可能会无法处理过高码率。

-movflags faststart 参数在流媒体播放的时候起作用,这个命令把视频容器的元信息移到文件头部。默认情况下(没有这个参数时),视频元信息在文件尾部,造成的结果是只有整个文件都加载完成后才能开始播放;有了这个参数,视频不必全部加载就可以播放。

Windows10 添加小鹤双拼

2022年08月14日更新:Windows 11 也可以使用本文的注册表方案。

Windows10 内置的微软拼音是一款出色的输入法。微软拼音虽然没有内置小鹤双拼的方案,但是提供了自定义双拼方案的功能,允许用户自行添加双拼方案。用户只需要将音节和按键配对即可。

不过,如果有多台设备的话,这样逐一手动配置双拼方案就显得过于笨拙了。更简单的方法是修改注册表,直接导入已经配置好的双拼方案。

自定义的双拼方案保存在 \HKEY_CURRENT_USER\Software\Microsoft\InputMethod\Settings\CHS 项中名称形如 UserDefinedDoublePinyinScheme0 (如果有多个方案,则名称的数值递增,如0、1、2…)的字符串值里。

经过手动配置,我的 UserDefinedDoublePinyinScheme0 值为 小鹤双拼*2*^*iuvdjhcwfg xmlnpbksqszxkrltvyovt 。

如果以后再需给微软拼音添加小鹤双拼方案,只需打开注册表编辑器,在 \HKEY_CURRENT_USER\Software\Microsoft\InputMethod\Settings\CHS 项中新建一个字符串值,将其命名为 UserDefinedDoublePinyinScheme0 (其中0也可能是1、2、3…),把它的值设置为 小鹤双拼*2*^*iuvdjhcwfg xmlnpbksqszxkrltvyovt ,就可以直接完成双拼方案的添加,而无需逐一手动配置。

当然,也可以直接下载注册表文件,然后导入注册表。

下载注册表文件压缩包(ZIP,412B)