如何理解 Spark NLP
跟进“如何在两周内开始 SparkNLP 第一部分”*
欢迎阅读 Spark NLP 文章的第二部分。在第一部分中,目标是为 NLP 从业者提供一个破冰的平台,并让他们对 Spark NLP 有所了解。对任何基于 Spark 的库的最大偏见来自于这样一种思想流派*“Spark 代码与常规 Python 脚本有点不同”*。为了消除这种偏见,我们分享了学习策略,如果你遵循了这些策略,你就为下一阶段做好了准备。
在本文的这一部分,我们将比较 spaCy 和 Spark NLP,并深入探讨 Spark NLP 模块和管道。我创建了一个笔记本,使用 spaCy 和 Spark NLP 来做同样的事情,进行完美的图片比较。SpaCy 表现不错,但是在速度、内存消耗、精度方面 Spark NLP 胜过它。因此,就易用性而言,一旦 Spark 的初始摩擦被克服,我发现它至少与 spaCy 不相上下,这要归功于管道带来的便利。
由 Spark NLP 创建者准备的 smart、comprehensive notebook的使用,提供了大量真实场景的示例,以及我为实践而创建的 repo 强烈建议在所需的技能集方面表现出色。
第 8/9 天:了解 Spark NLP 中的注释器/转换程序和使用 Spark 的 文本预处理
Spark NLP 库原生构建于 Apache Spark 和 TensorFlow 之上,为机器学习管道提供了简单、高效且准确的 NLP 符号,可在分布式环境中轻松扩展。这个库重用了 Spark ML 管道以及集成的 NLP 功能。
该库涵盖了许多常见的 NLP 任务,包括标记化、词干化、词汇化、词性标注、情感分析、拼写检查、命名实体识别,所有这些都是开源的,可以由训练模型使用您的数据。Spark NLP 的注释器利用基于规则的算法、机器学习和一些在引擎盖下运行的 Tensorflow 来支持特定的深度学习实现。
在 Spark NLP 中,所有的标注器要么是估算器,要么是变换器,就像 Spark ML 一样,由两种类型组成:标注器方法和标注器模型。任何在数据帧上产生模型的标注器训练都是标注器方法。那些通过一些模型将一个数据帧转换成另一个数据帧的是注释者模型(例如 WordEmbeddingsModel )。通常,如果注释器在转换数据帧时不依赖于预先训练的注释器(例如标记器),它就不会使用模型后缀。下面是注释器及其描述的列表:****
Spark NLP 提供的注释器列表,来源:Spark NLP 介绍—基础和基本组件
为了完成自然语言处理过程,我们需要对原始数据进行预处理。除了 SQL 过滤器、转换和用户定义的函数之外,Spark NLP 还附带了用于该任务的强大工具。Document assembler是一个特殊的转换器,它创建文档类型的第一个注释,这个注释可能会被管道中的后续注释器使用。
Doc2Chunk 将文档类型注释转换为带有块 Col 内容的块类型,而 Chunk2Doc 将块类型列转换回文档。在尝试对块结果进行重新标记或进一步分析时非常有用。
修整器 将注释值输出到一个字符串中,以方便使用。一旦我们的 NLP 管道准备就绪,我们可能希望在其他实际可用的地方使用注释结果。
如前所述,管道被指定为一系列阶段,每个阶段要么是转换器,要么是估计器。这些阶段按顺序运行,输入数据帧在通过每个阶段时会发生转换。
下面是这条管道在 Spark NLP 中的编码方式。
**from pyspark.ml import Pipelinedocument_assembler = DocumentAssembler()\
.setInputCol(“text”)\
.setOutputCol(“document”)sentenceDetector = SentenceDetector()\
.setInputCols([“document”])\
.setOutputCol(“sentences”)tokenizer = Tokenizer() \
.setInputCols([“sentences”]) \
.setOutputCol(“token”)normalizer = Normalizer()\
.setInputCols([“token”])\
.setOutputCol(“normal”)word_embeddings=WordEmbeddingsModel.pretrained()\
.setInputCols([“document”,”normal”])\
.setOutputCol(“embeddings”)nlpPipeline = Pipeline(stages=[
document_assembler,
sentenceDetector,
tokenizer,
normalizer,
word_embeddings,
])pipelineModel = nlpPipeline.fit(df)**
当我们在具有 Spark 数据帧(df)的管道上fit()
时,它的文本列首先被送入DocumentAssembler()
转换器,然后在文档类型(注释者类型)中创建一个新列“文档”。如前所述,这个转换器是任何 Spark 数据帧的 Spark NLP 的初始入口点。然后将它的文档列送入SentenceDetector()
( 注释者方法)中,将文本拆分成一个句子数组,并在文档类型中创建一个新列“句子”。然后将“句子”列输入到Tokenizer()
( 注释器模型)中,对每个句子进行标记化,并在标记类型中创建新列“标记”。诸如此类。请参考 Spark NLP workshop 预处理笔记本和 my repo 查看注释器和转换器的工作情况。****
第 10 天:Regex
正则表达式本质上是一种嵌入在 Python 中的微小的、高度专门化的编程语言,并通过 [*re module*](https://docs.python.org/3/library/re.html#module-re)
可用。 使用这个小语言,你为你想要匹配的可能字符串集合指定规则;这个集合可能包含英语句子,或者电子邮件地址,临床实体,或者任何你喜欢的东西。您还可以使用正则表达式来修改字符串或以各种方式拆分它。
Regex 是 NLP 的主要构件之一,我们不仅将使用它进行预处理,还将它作为 Spark NLP 管道中RegexMatcher
的一部分。由于有时可能相当复杂,我推荐 Maria Eugenia Inzaugarat 的这个课程,以便快速掌握高级主题,请参考官方 python 文档以及精彩的 python regex how to 教程。我用来掌握 regex 的另一个关键组件是 Regex101 ,这是一个非常强大的 API,可以让你在文本块上测试几乎任何正则表达式。
大多数时候正则表达式被忽略了。相信我:你会需要它,你会使用它。你知道的越多越好。
第 11 天:预训练模型
前面提到过,经过训练的标注器被称为标注器模型,这里的目标是通过指定的模型(经过训练的标注器)将一个数据帧转换成另一个数据帧。Spark NLP 提供多种语言的预训练模型,您需要做的就是加载预训练模型并相应地配置其参数。当您可以通过一种transform()
方法直接应用预先训练好的 SOTA 算法时,为什么还要担心从头开始训练新模型呢?在官方文档中,您可以找到关于如何使用哪些算法和数据集来训练这些模型的详细信息。笔记本样本可在此处找到。**
**MODEL_NAME='sentimentdl_use_twitter'documentAssembler = DocumentAssembler()\
.setInputCol("text")\
.setOutputCol("document")use = UniversalSentenceEncoder.pretrained(name="tfhub_use", lang="en")\
.setInputCols(["document"])\
.setOutputCol("sentence_embeddings")sentimentdl = SentimentDLModel.pretrained(name=MODEL_NAME, lang="en")\
.setInputCols(["sentence_embeddings"])\
.setOutputCol("pr_sentiment")nlpPipeline = Pipeline(
stages = [
documentAssembler,
use,
sentimentdl
])empty_df = spark.createDataFrame([['']]).toDF("text")pipelineModel = nlpPipeline.fit(empty_df)result = pipelineModel.transform(spark_df1)**
第 12/13 天:文本分类
Spark NLP 中有几个文本分类选项:
- Spark NLP 中的文本预处理和使用来自 Spark ML 的 ML 算法
- Spark ML 的 Spark NLP 和 ML 算法中的文本预处理和单词嵌入(Glove、Bert、Elmo)
- Spark ML 的 Spark NLP 和 ML 算法中的文本预处理和句子嵌入(通用句子编码器)
- Spark 自然语言处理中的文本预处理和分类器
你可以用这个ClassiferDL
在 Spark NLP 中构建一个包含Bert
、Elmo
、Glove
和Universal Sentence Encoders
的文本分类器。样本分类器笔记本可以在这里和这里找到。
**document_assembler = DocumentAssembler() \
.setInputCol("comment_text") \
.setOutputCol("document")\
.setCleanupMode('shrink')tokenizer = Tokenizer() \
.setInputCols(["document"]) \
.setOutputCol("token")
normalizer = Normalizer() \
.setInputCols(["token"]) \
.setOutputCol("normalized")\
.setLowercase(True)stopwords_cleaner = StopWordsCleaner()\
.setInputCols("normalized")\
.setOutputCol("cleanTokens")\
.setCaseSensitive(False)lemma = LemmatizerModel.pretrained('lemma_antbnc') \
.setInputCols(["cleanTokens"]) \
.setOutputCol("lemma")bert = BertEmbeddings.pretrained('bert_base_uncased', 'en') \
.setInputCols("document", "lemma") \
.setOutputCol("embeddings")\
.setPoolingLayer(0) # default 0embeddingsSentence = SentenceEmbeddings() \
.setInputCols(["document", "embeddings"]) \
.setOutputCol("sentence_embeddings") \
.setPoolingStrategy("AVERAGE")classsifierdl = ClassifierDLApproach()\
.setInputCols(["sentence_embeddings"])\
.setOutputCol("prediction")\
.setLabelColumn("toxic")\
.setMaxEpochs(5)\
.setEnableOutputLogs(True)\
.setBatchSize(32)\
.setValidationSplit(0.1)\
.setDropout(0.75)\
.setLr(0.0035)\
#.setOutputLogsPath('logs')clf_pipeline = Pipeline(
stages=[document_assembler,
tokenizer,
normalizer,
stopwords_cleaner,
lemma,
bert,
embeddingsSentence,
classsifierdl
])clf_pipelineModel = clf_pipeline.fit(sdf)**
第 13–14 天:SpaCy 或 Spark NLP —基准比较
在本节中,我们将获得大量的练习编码!我们将使用从 Gutenberg.org 下载的七部不同经典著作组成的图书馆。该语料库包括大约 490 万个字符和 9.7 万个句子。我们将使用 spaCy 和 Spark NLP 的类似过程构建相同的输出数据帧,然后比较结果。
Spacy 是我见过的记录最好的图书馆之一,我惊喜地发现现在他们包括了一门免费课程,我以前上过。如果需要的话,这是一个提升你技能的好机会。
比较的整个笔记本和语料数据可以在我的 GitHub repo 中找到。让我们从检查空间方式开始。
**### 2.1 Clean Tabs and Whitespace
clean_shrink = lambda text : text.replace(r'\n|\t|\s+',' ').replace('\s+',' ').strip()
df.loc[:,'document']=df.text.map(clean_shrink)### 2.2 Tokenizer
sentence_tokenizer = lambda sent : [token for token in nlp(sent)]
df.loc[:,'token']=df.document.map(sentence_tokenizer)### 2.3 Normalizer
normalizer = lambda tokens : [re.sub(punct,'',token.text) for token in tokens if re.sub(punct,'',token.text) != '']
df.loc[:,'normalized']=df.token.map(normalizer)### 2.4 Remove Stop Words
normalizer_and_stop = lambda tokens : [re.sub(punct,'',token.text) for token in tokens if re.sub(punct,'',token.text) != '' and not token.is_stop]
df.loc[:,'cleanTokens']=df.token.map(normalizer_and_stop)### 2.5 Lemmatize
normalizer_and_stop_lemma = lambda tokens : [re.sub(punct,'',token.lemma_) for token in tokens if re.sub(punct,'',token.text) != '' and not token.is_stop]
df.loc[:,'lemma']=df.token.map(normalizer_and_stop_lemma)### 2.6 Stemmer
stemmer = PorterStemmer()
stems = lambda tokens : [stemmer.stem(token.text) if len(tokens)>0 else [] for token in tokens]
df.loc[:,'stem']=df.token.map(stems)### 2.7 Part of Speech Tagging
normalizer_and_stop_pos = lambda tokens : [re.sub(punct,'',token.pos_) for token in tokens if re.sub(punct,'',token.text) != '' and not token.is_stop]
df.loc[:,'pos']=df.cleanTokens.map(normalizer_and_stop_pos)### 2.8 Token Assembler
token_assembler = lambda tokens : " ".join(tokens)
df.loc[:,'clean_text']=df.cleanTokens.map(token_assembler)### 2.9 Tagger
tagger = lambda text : [(ent.text, ent.label_) for ent in nlp(text).ents]
df.loc[:,'ner_chunks']=df.loc[:,'document'].map(tagger)### 2.10 Regex Parser
noun_chunker = lambda text : [(chnk,(chnk[0].pos_,chnk[1].pos_,chnk[2].tag_ ))for chnk in nlp(text).noun_chunks if len(chnk.text.split())==3\
and chnk.text.replace(' ','').isalpha() and chnk[0].pos_ == 'DET'and chnk[1].pos_ == 'ADJ' and chnk[2].tag_ in ['NN','NNP']
]
df.loc[:,'RegexpParser'] =df.loc[:,'document'].map(noun_chunker)**
让我们暂停一下,观察正则表达式解析器的输出。我们要求名词组块器返回由一个限定词、一个形容词和一个名词(专有、单数或复数)组成的组块。
**[chunk for chunk in df.RegexpParser.values if chunk!=[]]**
结果看起来相当不错。
**[[(My dear Robinson, ('DET', 'ADJ', 'NNP'))],
[(this accidental souvenir, ('DET', 'ADJ', 'NN'))],
[(a great deal, ('DET', 'ADJ', 'NN'))],
[(a great amount, ('DET', 'ADJ', 'NN'))],
[(the local hunt, ('DET', 'ADJ', 'NN')),
(some surgical assistance, ('DET', 'ADJ', 'NN'))],
[(a remarkable power, ('DET', 'ADJ', 'NN'))],
[(a good deal, ('DET', 'ADJ', 'NN'))],
[(a fresh basis, ('DET', 'ADJ', 'NN')),
(this unknown visitor, ('DET', 'ADJ', 'NN'))],
[(the obvious conclusion, ('DET', 'ADJ', 'NN'))],
[(their good will, ('DET', 'ADJ', 'NN'))],
[(my dear Watson, ('DET', 'ADJ', 'NNP')),
(a young fellow, ('DET', 'ADJ', 'NN'))],
[(a favourite dog, ('DET', 'ADJ', 'NN'))],
[(the latter part, ('DET', 'ADJ', 'NN'))],
[(that local hunt, ('DET', 'ADJ', 'NN'))],
[(a heavy stick, ('DET', 'ADJ', 'NN'))],
[(a professional brother, ('DET', 'ADJ', 'NN'))],
[(the dramatic moment, ('DET', 'ADJ', 'NN'))],
[(a long nose, ('DET', 'ADJ', 'NN'))],
................**
让我们继续搭积木吧。
**### 2.11 N-Gram Generator
ngram_generator = lambda input_list: [*zip(*[input_list[i:] for i in range(n)])]
n=3
df.loc[:,'triGrams'] = df.loc[:,'token'].map(ngram_generator)### 2.12 Word2Vec Embeddings
vector = lambda tokens: [(token.text, token.has_vector, token.vector, token.is_oov) for token in tokens]
df.loc[:,'vectors'] = df.loc[:,'token'].map(vector)### 2.13 Regex Matcher
rules = r'''\b[A-Z]\w+ly\b|Stephen\s(?!Proto|Cardinal)[A-Z]\w+|Simon\s[A-Z]\w+'''
regex_matchers = lambda text : re.findall(rules,text)
df.loc[:,'Regex_matches'] =df.loc[:,'document'].map(regex_matchers)**
让我们来看看正则表达式匹配
**df.Regex_matches[df.Regex_matches.map(len)>1]**
结果如下:
**13123 [Polly, Polly]
25669 [Sally, Sally]
27262 [Sally, Sally]
27273 [Polly, Sally]
27340 [Polly, Sally]
28311 [Pelly, Dolly]
42016 [Feely, Feely]
49802 [Finally, Emily]
52129 [Lively, Lively]
58295 [Silly, Milly]
62141 [Silly, Milly]
64811 [Only, Molly]
71650 [Hely, Daly]
74427 [Healy, Dolly]
77404 [Molly, Milly]
77437 [Milly, Molly]
81557 [Molly, Reilly]
84023 [Szombathely, Szombathely]
89594 [Healy, Joly]
92206 [Simon Dedalus, Stephen Dedalus]
92980 [Firstly, Nelly, Nelly, Nelly]
93046 [Szombathely, Karoly]
94402 [Reilly, Simon Dedalus, Hely]
94489 [Stephen Dedalus, Simon Dedalus]**
让我们冒险进入角色…
既然我们有了一个包含许多要素的数据集,我们就有了大量的选项可供选择。让我们检查一下书中的人物……让我们找到带有“人”标签的 NER 语块,由两个单词组成。
**flatlist = lambda l : [re.sub("[^a-zA-Z\s\']","",item[0]).title().strip() for sublist in l for item in sublist if item[1]=='PERSON' and len(item[0].split())==2]
ner_chunks = df.ner_chunks.to_list()
names=(flatlist(ner_chunks))
len(sorted(names))**
上面的代码返回了 4832 个名字,这看起来有点可疑,因为这个数字很高。让我们检查一下Counter
对象的结果:
**('St Clare', 306),
('Buck Mulligan', 96),
('Aunt Chloe', 76),
('Martin Cunningham', 74),
('Masr George', 45),
('Ned Lambert', 44),
('Solomon Northup', 43),
('Tom Sawyer', 42),
('Aunt Sally', 37),
('Uncle Tom', 37),
('Ben Dollard', 36),
('Myles Crawford', 35),
('Blazes Boylan', 28),
('Uncle Abram', 24),
('J J', 22),
......
('L L', 5),
('Mark Twain', 5),
("Tom Sawyer'S", 5),
('Chapter Xi', 5),
('Chapter Xix', 5),
('Dey Wuz', 5),
('George Jackson', 5),
('Levi Bell', 5),
('King Lear', 5),
('Simon Legree', 5),
('Garrett Deasy', 5),
('A E', 5),
('S D', 5),
('Josie Powell', 5),
('Mrs Purefoy', 5),
('Ben Howth', 5),
('Bald Pat', 5),
('Barney Kiernan', 5),
('Michael Gunn', 5),
('C C', 5),**
不幸的是,许多标签是不准确的。请注意一些章节标题以及大写首字母被错误地返回为PER
标签。
在编写上面的代码时,使用了映射来确保快速调整,并且模拟了下面将要实现的 Spark NLP 管道。一旦我们在 Spark NLP 中运行类似的代码,我们将在内存使用、速度和准确性方面比较结果。
是时候用 NLP 的方式做事了!
**documentAssembler = DocumentAssembler()\
.setInputCol(“text”)\
.setOutputCol(“document”)\
.setCleanupMode(“shrink”)sentenceDetector = SentenceDetector().\
setInputCols(['document']).\
setOutputCol('sentences')tokenizer = Tokenizer() \
.setInputCols(["sentences"]) \
.setOutputCol("token")ngrams = NGramGenerator() \
.setInputCols(["token"]) \
.setOutputCol("ngrams") \
.setN(3) \
.setEnableCumulative(False)\
.setDelimiter("_") # Default is spacenormalizer = Normalizer() \
.setInputCols(["token"]) \
.setOutputCol("normalized")\
.setLowercase(False)\
.setCleanupPatterns(["[^\w\d\s\.\!\?]"])stopwords_cleaner = StopWordsCleaner()\
.setInputCols("normalized")\
.setOutputCol("cleanTokens")\
.setCaseSensitive(False)\lemma = LemmatizerModel.pretrained('lemma_antbnc') \
.setInputCols(["cleanTokens"]) \
.setOutputCol("lemma")stemmer = Stemmer() \
.setInputCols(["token"]) \
.setOutputCol("stem")pos = PerceptronModel.pretrained("pos_anc", 'en')\
.setInputCols("clean_text", "cleanTokens")\
.setOutputCol("pos")chunker = Chunker()\
.setInputCols(["sentences", "pos"])\
.setOutputCol("chunk")\
.setRegexParsers(["<DT>+<JJ>*<NN>"]) ## Determiner - adjective - singular nountokenassembler = TokenAssembler()\
.setInputCols(["sentences", "cleanTokens"]) \
.setOutputCol("clean_text")\tokenizer2 = Tokenizer() \
.setInputCols(["clean_text"]) \
.setOutputCol("token2")glove_embeddings = WordEmbeddingsModel.pretrained('glove_100d')\
.setInputCols(["document", "lemma"])\
.setOutputCol("embeddings")\
.setCaseSensitive(False)onto_ner = NerDLModel.pretrained("onto_100", 'en') \
.setInputCols(["document", "token", "embeddings"]) \
.setOutputCol("ner")ner_converter = NerConverter() \
.setInputCols(["sentences", "token", "ner"]) \
.setOutputCol("ner_chunk")rules = r'''
\b[A-Z]\w+ly\b, starting with a capital letter ending with 'ly'
Stephen\s(?!Proto|Cardinal)[A-Z]\w+, followed by "Stephen"
Simon\s[A-Z]\w+, followed by "Simon"
'''with open('ulyses_regex_rules.txt', 'w') as f:
f.write(rules)regex_matcher = RegexMatcher()\
.setInputCols('sentences')\
.setStrategy("MATCH_ALL")\
.setOutputCol("regex_matches")\
.setExternalRules(path='./ulyses_regex_rules.txt', delimiter=',')**
既然我们的零件都准备好了,让我们来定义装配线。
**nlpPipeline = Pipeline(stages=[
documentAssembler,
sentenceDetector,
tokenizer,
ngrams,
normalizer,
stopwords_cleaner,
lemma,
stemmer,
tokenassembler,
tokenizer2,
pos,
chunker,
glove_embeddings,
onto_ner,
ner_converter,
regex_matcher
])empty_df = spark.createDataFrame([[‘’]]).toDF(“text”)pipelineModel = nlpPipeline.fit(empty_df)lib_result = pipelineModel.transform(library)**
****让我们根据我们的搜索标准检查 regex 匹配:
-以大写字母开头并以’ ly '结尾的整个单词,
- 'Stephen ‘后面没有’ Cardinal ‘或’ Proto ',但后面有以大写字母开头的单词。–“Simon”后面是一个以大写字母开头的单词。我们希望每个句子中至少出现两次…****
**match_df.filter(F.size('finished_regex_matches')>1).show(truncate = 50)**
让我们来看看结果…
我们管道中的 chunker 注释器将返回由限定词、形容词和单数名词组成的组块。
**lib_result.withColumn(
"tmp",
F.explode("chunk")) \
.select("tmp.*").select("begin","end","result","metadata.sentence").show(20,truncate = 100)**
以下是 chunker 结果的前 20 行。
让我们冒险进入角色…火花 NLP 方式。
在这里,我们检查书中的角色…这一次我们将使用 Spark NLP 机制。请注意准确性与空间的差异。
**l = result_ner.filter(result_ner.ner_label == "PERSON").select(F.expr("ner_chunk")).collect()names = list([re.sub("[^a-zA-Z\s\']","",l_[0]).title() for l_ in l if l_[0].replace(' ','').isalpha() and len(l_[0].strip().split())==2 and "’" not in l_[0]])len(set(names))**
这一次,我们的字符数被限制在 1284。让我们来看看最常见的 350 个名字。
**('Buck Mulligan', 93),
('Aunt Chloe', 82),
('Martin Cunningham', 71),
('Bayou Boeuf', 48),
('Aunt Sally', 39),
('Ned Lambert', 39),
('Mary Jane', 38),
('Solomon Northup', 36),
('John Thornton', 34),
('Myles Crawford', 33),
('Ben Dollard', 31),
('Sherlock Holmes', 30),
('Tom Sawyer', 30),
('John Eglinton', 29),
('Nosey Flynn', 28),
('Corny Kelleher', 27),
('Mrs Breen', 27),
('Father Conmee', 26),
('Uncle Tom', 25),
('John Wyse', 24),
('Henry Baskerville', 23),
('Uncle Abram', 22),
('Blazes Boylan', 19),
('Bob Doran', 18),
('Davy Byrne', 18),
('Coombe Tracey', 17),
('Aunt Phebe', 17),
('Simon Dedalus', 17),
........................
('Sandy Hill', 8),
('Theophilus Freeman', 8),
('Father Cowley', 8),
('Gregory B', 7),
('George Harris', 7),
('Rachel Halliday', 7),
('George Shelby', 7),
('Anne Hampton', 7),
('Peter Tanner', 7),
('Almidano Artifoni', 7),
('Hugo Baskerville', 6),
('Laura Lyons', 6),
('Aunt Polly', 6),
('Peter Wilks', 6),
.........................**
名单看起来更准确。难怪 Spark NLP 是企业首选!
SpaCy 不错,但是 Spark NLP 更好…
我们来谈谈资源消耗:
本次研究使用的系统是一个 8 核英特尔酷睿 i7–9700k CPU @ 3.60 GHz,32820MB 内存。操作系统是 Ubuntu 20.04。
与 spaCy 相比,Spark NLP 使用的内存更少,运行速度是 spaCy 的两倍。这个事实,再加上 Spark NLP 更高的准确性,为掌握这个库提供了很好的理由!
目前就这些。本文的主要目的是给中级水平的从业者一个如何使用 Spark 在 NLP 领域实现目标的指南。一些 Spark NLP 概念在开始时可能很难学习,但是,本文中介绍的文章、课程和示例笔记本将提供一个很好的起点。spaCy-Spark NLP 的初始开销可能很高,但比较显示了差异。掌握 Spark NLP 并不容易,但也不太难…如果你的目标是企业领域,这绝对是一项让你在简历上大放异彩的技能!
请点击链接进入文章的第一部分。
如何用 Python 编写一个数字系统计算器
二进制,十进制或十六进制,冲我来,兄弟!
照片由来自 Pexels 的安德里亚·皮亚卡迪奥拍摄
在本文中,我们将构建一个计算器,可以用来将任意基数的任意数字转换成任意基数的任意数字。在数字系统中,“基数”告诉我们你有多少个可用的数字。二进制有 2,八进制有 8,十进制有 10 等等。
我们将要编写的程序可以处理我们扔给它的任何number
和base
。当我们搞清楚背后的数学,就很容易成立了。
我们将创造什么:
但是首先,数学
这个计算器是以数学为基础的(不都是吗?).我们可能需要刷新我们对碱基转换理论的记忆(或者学习一些新的东西。)
如果你在学校学过科学驱动的数学,或者学过任何级别的计算机,你很可能已经从一种数字系统转换到另一种了。你可能还记得二进制表或者谈论过的"十进制",**八进制",十六进制"。
十进制(以 10 为基数)是我们日常计数时使用的。0, 1, 2, 3, 4, 5, 6, 7, 8, 9.当我们用完了数字,我们在左边再加一个位置→ 10,11,12,13,14,15,16,17,18,19,20,21…等等。当我们再次用完数字时,我们添加一个新的位置→ 100,101,102…118,119,120。
是的,是的…我记得小学…
我们不会去想它,因为我们在 2-3 岁的时候就知道了。告诉一个孩子用八进制(8 进制)数数,他们很可能会看你几秒钟,然后再回到他们的 iPad 上做作业。这个理论很简单,与十进制相同,只是我们不习惯。
在八进制系统中计数看起来像这样:
0,1,2,3,4,5,6,7 → 10,11,12,13,14,15,16,17 → 20,21…
从一个碱基转换到另一个碱基
我们应该看的第一个转换是从任意基数(基数为 N)到十进制系统(基数为 10)。从十进制转换成任何其他基数都很容易。因此,了解十进制是很有价值的。
如果我们继续使用十进制的和八进制的和作为例子,我们可以将八进制的转换成十进制的。让我们选一个随机数。**
256(基数-8) →???(十进制)
(我保证,256 实际上是随机的)
- 我们有三个位置 2(一百)、5(十)和 6(一)。正如您在简介中所记得的,这些位置可以包含 0-7(8 个数字)。
- 我们需要将所有位置的每个数字都转换成十进制。十进制系统可以容纳 0–9(10 个数字)
我们这样做的方法是,我们取每一个数,并把它乘以以位置索引为幂的基数(num * (base^position)).如果我们从最右边的数字开始,我们用 8⁰乘 6,用 8 乘 5,用 8 乘 2。
这里有一个例子可以让你更容易理解:
从基数为 8 的 256 到基数为 10 的 174
当我们有了十进制(以 10 为基数)的数字,就很容易进入任何系统。让我们从 174(基数为 10)回到 256(基数为 8)
我们找到另一个基数的方法是用它除以这个基数,并保留余数。剩下的人会在另一个基地给我们建号码。当我们得到余数时,我们从最不重要的数字到最重要的数字来读这个数,意思是从下到上。你的新号码出现在你的新底座上了!
174/2 等于 21.75。注意 21 是红色的,0.75 是绿色的。我们把 21 送到下一行,处理 0.75。如果我们用 0.75 乘以基数,就剩下余数(这是我们要找的数)。这个数字以蓝色发送到最右边。
当我们达到 0 时,我们就正式完成了,可以在我们的新基地用一个漂亮的数字打包我们的行李了。
从基数 10 的 174 到基数 8 的 256
这不仅意味着我们可以从十进制到八进制,反之亦然。我们可以从 X 基到 y 基。任何我们想要的基。
感觉大概是这样的:
照片由来自 Pexels 的 Marcin Dampc 拍摄
如果你仍然不确定这是如何工作的,我建议查看“有机化学导师”。他的视频是我所知道的关于这个主题的最好的:
该频道主要提供有机化学、普通化学、物理、代数等方面的教学视频
www.youtube.com](https://www.youtube.com/channel/UCEWpbFLzoYGPfuWUMFPSaoA)
代码
是时候深入研究代码了!
注意:我的大部分编程都是手工完成的。这意味着我不使用太多的库,因为我想尽可能多地学习。在这段代码中,我使用了之类的标准 python 函数,因为我想向您展示这是可能的,但我认为手动编写相同的函数比使用hex()
更有趣。在生产环境中,您可能希望保持简短,并使用能够解决您的问题的库,而不是从头开始编写代码
这个程序只是一个包含所有代码的文件。如果你愿意,你可以随意扩展。一节数字课?当然,为什么不呢?GUI?这也是我们应该研究的。
我建议在编码时使用一个基本的在线转换器计算器,仔细检查代码输出的值是否正确。
要点如下:
完整的要点代码。
代码背后的逻辑是我们向函数convert_number_system():
传递三个参数
input_number
是我们要转换的数字。input_base
是我们希望转换的基础。output_base
是我们希望皈依的基地。
定义菜单()
我以前没有使用多行字符串来打印菜单,但是创建这样的菜单是很有意义的。
该函数返回整个菜单字符串,因此我们可以在任何需要的地方使用它。我们也不用担心换行符。
return (
'''
----------------------------------------------------------
Welcome to the Number Base converter!
The system will ask you for:
- The Number to convert
- What base you want to convert FROM
- What base you want to convert TO** REMEMBER: All numbers must be integers!(unless HEX) **
----------------------------------------------------------
''')
验证器
我不想在转换器函数中检查用户输入,而是想创建函数形式的验证器。通过这样做,我们创建了可重用的代码。
def validate_bin(检查编号):
这个函数只是检查数字是否是有效的二进制数。
我们不想检查同一个数字出现了几次的长字符串。如果我们把它转换成一个集合,我们删除重复。集合不能包含一个项目的多个实例。我们使用 list comprehension 将输入转换为 int,并对照[0,1]进行检查
[int(item) for item in set(list(check_number))]
我选择传递来自用户交互的字符串,并在需要时创建输入的整数。int(item)
确保所有的数字都是整数(如果我们愿意,我们也可以对照一个字符串来检查一个字符串(‘0’ , ‘1’
)。
这是它在幕后的样子:
‘10010011’
→ [‘1’,’0',’0',’1',’0',’0',’1',’1']
→ [0,1]
如果 0 在[0,1]中,则检查结果正常,如果 1 在[0,1]中,则检查结果也正常。如果你有一个像 23 这样的数字,两个数字都会失败,函数会返回False
定义验证输入(检查编号):
这里没有什么特别的…代码检查输入是否包含定义的合法字符。我们使用数字0–9
,因为我们支持十六进制,所以我们也将a-f
作为有效输入。
定义验证器(输入编号,输入基础,输出基础):
这个函数利用其他验证器来验证所有的输入,这样我们就知道是否有必要继续进行转换。
- 首先,它检查我们是否输入了一个数字或十六进制值。
- 然后我们检查基地。如果 input_base 是 2,那么我们正在转换一个二进制数。因此,input_number 只能是数字,如果是,它必须是 0 或 1。
- 如果输入既是数字又是字母,则它是一个十六进制数字。如果 input_base 不是 16,那么我们就不能转换。十六进制以 16 为基数,任何其他基数都不会正确计算。我们可以考虑在交互过程中,当有人键入十六进制数时,制作一个预填充的输入库。
- 最后,我们检查用户是否试图转换为基数 1。这是不可能的,所以我们不想让程序崩溃,而是想返回一个错误。*
转变
现在,该是代码的主要部分了。这是我们将利用我们的数学技能的地方。这个函数执行我们之前看到的匹配,它有几个安全步骤来确保我们正确输出
def convert _ number _ system(input _ number,…):
转换 _ 数字 _ 系统要点
保存我们要返回的数字。如果你记得数学,你应该立刻认出关键字余数。
sum_base_10
。我们想用十进制作为中间步骤。我们将初始值设置为 0,然后将我们计算的任何值添加到这个变量中。
输出二进制:
*if output_base == 2:
return (bin(input_number)[2:])*
如果用户想要二进制输出,我们可以使用内置函数 bin()。我们不需要这样做,因为无论我们通过了什么,数学都是一样的,但是尝试是很有趣的。
bin()
返回0b
和二进制。0b
告诉我们它是一个二进制数。我们想返回实际的数字。这就是[2:]的作用。如果您在终端中运行此命令,您可以看到不同之处:
*>>> check_number = 23
>>> print(bin(check_number))
0b10111
>>> print(bin(check_number)[2:])
10111*
它将从索引 2 开始打印。
注意,我在代码中保留了 hex()版本,但是注释掉了。你想用就用吧。
基数不是 10: 如果基数不是 10,我们通过我们的中间步骤。首先,我们反转列表(你不必这样做,但是之后你需要在循环中翻转索引。我发现翻转列表更容易。)用这个神奇的内置代码[::-1]可以在 Python 中反转列表
*reversed_input_number = input_number[::-1]*
hex_helper_dict 帮助我们处理 9 以上的数字,如果用户发送一个十六进制输入。如果你还记得我们的公式,我们将每个位置的数字乘以由位置决定的基本指数。
这里又是 256 从八进制到十进制:**
2(8²) + 5*(8¹) + 6*(8⁰) = 174*
如果数字是十六进制的,比如 23e,它实际上是 2,3,14
2(16²) + 3*(16¹) + 14*(16⁰) = 574*
这个循环帮助我们完成了所有这些工作:
*for index, number in enumerate(reversed_input_number):
for key,value in hex_helper_dict.items():
if str(number).lower() == key:
number = value sum_base_10 += (int(number)*(int(input_base)**index))*
如果你看看上面的代码,你会发现我们同时使用了枚举和。items()来确保我们可以访问执行操作所需的所有内容。
通过使用枚举,我们可以访问变量的值和索引。当我们循环变量时,我们检查数字(例如。e
)等于字典中的任意一个键。在 23e 的情况下,它是,我们想将数字设置为 14,这样我们可以使用它进行实际计算。
*sum_base_10 += (int(number)*(int(input_base)**index))*
既然我们已经确定没有数字是真正的字母,我们就可以遍历这些数字(还是 256)并进行运算。对于我们循环遍历的每个数字,我们都要做之前讨论过的乘法。
(int(number)(int(input _ base)* * index))
6 (8 * * 0)
我们最终得到的值被加到 sum_base_10。
基数是 10: 太棒了,继续。我们只是将输入数赋给 sum_base_10:
*elif input_base == 10:
sum_base_10 = int(input_number)*
做数学运算 现在我们有了以 10 为基数的值,我们可以做除法来找出余数并找到我们的新数。
*while sum_base_10 > 0:
divided = sum_base_10// int(output_base)
remainder_list.append(str(sum_base_10 % int(output_base))
sum_base_10 = divided*
我们需要除法,直到我们达到 0。while 循环确保了这一点。
通过使用底数除法//我们将数除,剩下的是商的整数部分。这意味着我们只保留整数(21)而不保留点(75)之后的内容,这是基于我们在 intro (174/8= 21.75 )中的例子
通过将这个数分配给 divided,我们还可以将这个值发送给 sum_base_10,以便最终进行下一次迭代。
通过使用模,%,我们将得到余数。这被附加到 remainder_list 中,这样我们可以在以后输出它。
这是一个 while 循环,一直持续到我们点击0
如果输出基数是 16 如果 output_base 是 16,这意味着用户想要一个十六进制输出。我们需要将任何大于 9 的数字转换成字母。
正如我们之前所做的,我们创建了一个字典来帮助转换。如果我们找到一个匹配,我们把数字转换成一个字母,并把它附加到列表中。
最后:
*return ''.join(remainder_list[::-1])*
这反转并把我们的列表变成一个我们可以返回的字符串。如果要返回一个 int,可以使用 int()。如果用户要求 16 进制输出,请确保您考虑了十六进制数。
def 执行转换器():
唷!我们的大部分代码已经完成。
拼图的最后一块是与用户互动。这是一个直接的 while 循环,用户输入数字,我们验证它们,如果验证通过,就运行转换器。用户可以选择他/她想要做多少次就做多少次。
我喜欢用基于变量状态的 while 循环来创建用户交互;就像我们这里的proceed
。这样,只要用户愿意,我们就可以一直进行下去。
它有两个层次。第一个 while 根据proceed.lower() == ‘y’.
启动主循环
第二个声明valid_input=False
,因为我们希望在将输入传递给convert_number_system()
之前验证所有的输入。只要输入是False
,我们就需要新的输入。在用户给我们他/她的输入之后,它运行验证器。如果通过,我们可以启动convert_number_system()
最后,我们询问用户是否想再去一次。如果用户输入‘y’,我们再次运行代码。如果他/她再输入任何东西,我们就退出程序。
另一种方法是要求用户键入他/她想要转换的号码或退出。在number_input
变量中。
最后
这个程序涵盖了编程的几个方面。首先,我们需要找到问题。问题是手动转换所有的数字要花很多时间。
然后我们找到/学习数学来解决问题,找到共同点。事实证明,我们可以用相同的公式将任何东西转换成任何东西。我们只需要处理二进制和十六进制输入,我们需要确保我们不会试图计算基数为 1。这意味着我们可以使用函数来处理我们的代码。
一切都包装在一个菜单里,一个用户交互,底层执行代码潜伏在后台。
我希望你通过阅读这篇文章学到了一些东西。如果你发现任何问题的代码或有其他想法,请让我知道。请随意获取代码,并继续为您自己的项目开发它。
-M
如何和杰西一起写 algotrading 比特币的盈利策略
开始使用算法交易并不难
照片由 Katerina Limpitsouni 拍摄
在这个教程里,我要写一个和杰西交易比特币的策略。本教程的重点是让你开始使用 Jesse,这样你就可以编写自己的策略。我还会教你几个技巧,这些技巧是我多年来学到的,可以帮助我写出有利可图的策略。这大概会是一系列的文章。
本教程的重点不是给你一个牛逼的策略;这是让你开始写一个。在第一部分中,我将涵盖从:
- 如何使用技术分析
- 如何进入交易
- 如何退出交易
- 如何管理风险
首先,确保您已经安装了 Jesse。如果没有,那就去做吧。接下来,确定你进口了蜡烛。我们现在就开始吧,因为这需要几分钟才能完成,这很好,因为我们将编写策略:
jesse import-candles Bitfinex BTCUSD 2016-01-01
创建策略
我们把这个策略命名为SampleTrendFollowing
。cd
进入您的 Jesse 项目并运行:
jesse make-strategy SampleTrendFollowing
现在打开位于strategies/SampleTrendFollowing/__init__.py
的SampleTrendFollowing
。这是 Jesse 生成的代码:
使用技术分析
我们将使用均线指标来检测市场趋势的方向。让我们用两条周期为 50 的均线代表慢速均线,周期为 21 的均线代表快速均线。
注意,我用@property
关键字将它们定义为类属性。这允许我将它们用作self.long
而不是self.long()
,在我看来这更容易一些。
让我们也定义一下 ATR 指标,这是我最喜欢的设定止损价格的工具:
进入规则
我们的进场规则很简单:当快速均线突破慢速均线时做多,反之亦然。
管理风险
每个策略的一个关键部分是头寸规模。一个简单的组合头寸规模将使你受益匪浅。例如,让我们每次交易都拿总资本的 3%来冒险。
我们还需要指定我们的入门价格。简单来说,让我们用市价单建仓。
注意,我在止损和止盈目标中都使用了ATR
指标。
虽然动态退出趋势跟踪策略是一个很好的实践,但是我在开仓的时候设置了退出点。我这样做是为了保持本教程简单。
路线
现在我们需要告诉 Jesse 在执行回溯测试命令时交易SampleTrendFollowing
策略。我们还需要选择一个时间框架,和一个交易的符号。我选择了6h
时间框架和BTCUSD
作为我的标志。您的routes.py
文件应该如下所示:
运行回溯测试
让我们看看它的表现如何:
jesse backtest 2019-01-01 2020-01-01
结果如下:
你看那个,居然有利可图!嗯,至少在 2019 年是这样。对于在6h
时间框架内的趋势跟踪策略交易来说,这样的回溯测试足够了吗?你说了算,但如果我有数据,我会更进一步。在这种情况下,我回到 2017 年,直到今年的 5 月 3 日:
结论
本教程的目的是让你开始和 Jesse 一起编写策略。我将写更多这样的文章,探索 Jesse 的更多特性,比如使用多个时间框架、过滤器、事件等等。
为了获得我未来的作品和产品,请务必订阅杰西的时事通讯,并查看论坛,与你我这样的量化者讨论算法交易。
**更新【5 月 26 日】😗*下一篇文章继续这篇文章的结尾:
如何在你的算法交易策略中使用多个时间框架
来自《走向数据科学》编辑的注释: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
如何写一份成功的目标陈述
帮助我被卡内基梅隆大学、斯坦福大学、加州大学伯克利分校的计算机科学研究生课程录取的 8 个技巧和例子
https://unsplash.com/photos/s9CC2SKySJM
大约在去年的这个时候,我开始准备美国大学的研究生申请,以攻读涉及人工智能的硕士项目。从法国一个全新的学士项目的第一批毕业生中毕业,我几乎没有研究或行业经验,也没有发表过论文,但我比以往任何时候都更有决心写一份目标陈述(SoP ),这将有助于我从优秀的申请者中脱颖而出。
几个月后,我很高兴收到了我所有首选的录取通知书!虽然一开始我不知道 SoP 是什么,但我肯定做了一些正确的事情,说服了所有这些名牌大学的人。为了回馈社区,我想分享一些我在 SoP 写作过程中学到或发现有用的技巧:)
对于那些感兴趣的人,我也会在这篇文章的最后附上我在申请期间的统计数据,我被接受的项目,我被拒绝的项目,以及我选择的项目。
免责声明:我只是一个喜欢机器学习和博客的应届毕业生,我绝对没有资格教你如何写论文。以下建议仅仅反映了我申请美国计算机硕士学位的个人经验,并不总是通用的。
1.不要拖延这篇文章
是的,我很清楚一个学生在最后一分钟完成一篇论文时的超人生产力。但是相信我,我强烈建议你在申请截止日期之前就开始考虑你的 SoP。
以下是我的时间表:
九月开始*——我在谷歌上搜索“如何写目标陈述”并创建了我的 SoP.docx 文件*
十月开始——我准备好了第一份草稿,请其他人校对
11 月开始——我修改了我的第一稿,让其他人再次校对
11 月底——我准备好了一份“通用”SoP,但我仍需对我考虑的每个项目进行“微调”
12 月-1 月——对于每个项目,我在提交申请前都敲定了每个 SoP
2 月 3 日 —我收到了我的第一个回复:被我的梦想计划录取了!
对我来说,花了 3 个月来计划和写我的 SoP。有些可能需要更多或更少的时间。我的观点是,这不是一篇可以或应该仓促完成的文章,给自己时间思考你想说的话,从别人那里得到的反馈,再重写几次就好了。
如果你不知道如何开始,我的建议是无论如何都要创建文档,记下你的任何想法,即使是愚蠢的想法。从那里,你将能够开始把这些想法串成一串文本,或者在你没有预料到的时候想出新的想法。
2.目的陈述≠个人陈述
与我本科申请的个人陈述不同,大多数研究生院不会给出明确的提示或你需要回答的问题。一个常见的错误是认为毕业生 SoP 就像是“有更多经验的个人陈述”。
个人陈述是个人,你应该写你是谁。
另一方面,目标陈述应该围绕你计划实现的目标。
一般来说,您应该在 SoP 中回答的重要问题有:
- 你的兴趣、动机和目标是什么?是什么激发了他们?
- 你在有什么相关经验?你学到了什么让你为研究生学习做好准备?
- 这个研究生项目如何帮助你实现目标?在这个项目中你打算做什么?
请记住,审稿人实际上是在你的论文中寻找成为成功研究生的潜力,所以你的主要目标是让你相信自己有能力、有动力去完成研究生学业。
3.保持结构化
你希望你的 SoP 能让你的评审者愉快地阅读。重要的是,你的想法是有结构的,流畅的,这样评审者就不需要猜测你想表达什么或者在想法之间跳跃。
我是这样组织我的文章的:
- 在陈述我的总体目标之前,抓住读者的注意力
- 描述我以前实现这个目标的经历
- 陈述我学到了什么和使我成功的品质
- 重申目标,但提供更多细节
- 解释我还需要学习什么,以及该计划将如何帮助我成长
- 以热情、积极的语气结束:)
你的可能看起来不像我的,但总的来说就是每个段落/部分都有一个清晰的 信息/目的。
4.保持简洁、相关、专注
一个好的经验法则是将你的文章控制在两页以内。尽管你可能有很多话要说,但对你想要包含的细节进行选择是很重要的,因为评论者可能有数百篇文章要看。
对我起作用的是,一开始写下我想要的一切,然后改写冗长的短语,省略不必要的细节。确保你说的每一句话都是一个关键细节,说明你为什么是理想的研究生候选人。
同样,问问你自己*“我想用这个传达什么信息?”对于每一句话。不要只是描述你在项目中做了什么,一定要陈述你从中学到了什么**,这个证明了关于你的什么:*
在我的第一个编程项目中,我带领一个 8 人团队用 C++为音乐创作构建了一个 LSTM 神经网络。在项目开始时,我没有机器学习经验,在 4 个月内,我吸收了建立和训练神经网络所需的技术技能和机器学习概念。我还学会了设计一个机器学习项目,从数据检索和嵌入到模型演示的用户界面,并在团队中有效地分配这些任务。
5.从一开始就引人注目
理想的文章从一开始就能抓住读者的注意力,并引导他们理解你的想法,直到最后。不要泛泛而谈,要有创意!
不要以“我的目标是研究人工智能和开发帮助人们的技术”——这不会让你的介绍令人难忘或迷人——开始你的文章,而是想一件轶事,一个参考,甚至一个笑话,帮助你轻松进入你的主要信息。
在继续解释我的研究目标之前,下面是我如何开始的:
我妈妈刚开始用智能手机的时候,只用来打电话。她不会使用其他功能,例如查找方向,直到我教她口头询问虚拟助理她需要什么。这让我相信自然语言处理将会在人类和现代技术之间架起一座桥梁。
6.秀,不要说
招生人员正在寻找证据,证明你最适合他们的项目。任何人都可以说“我很有决心,工作努力,而且我学东西很快”,但这不会让你出类拔萃。
一个更强烈的信息是举一个例子,无论是在工作中、课堂上还是在外面,展示了你声称拥有的品质。例如,下面是我说的话,而不是“我很有决心,很努力”:
在人工智能方面的经验很少的情况下,我参加了 4 次社交活动,分发了 50 份简历,参加了 10 次面试,从而获得了 NLP 实习机会。
7.具体说明你所在的领域和你的项目
与本科学习不同,研究生招生寻找的是在项目学习领域与他们密切合作的学生。你是他们潜在的研究助理,助教,博士生…
你需要向他们展示你知道他们在做什么样的工作,并且你拥有适合他们专业领域的 T2 特有的技能。在描述你的经历时,不要犹豫使用专业术语!
在熟悉了语言建模和自我关注之后,我在最近的研究基础上使用完形填空翻译来合成问题回答数据。我还学会了在 PyTorch 中编写 BiDAF 和 BERT 模型,并执行云计算。
此外,跟踪你项目中的一些教员和活动也很好,并表明这不仅仅是的任何项目,而是你想要的这个特定的项目。你可以引用你感兴趣的论文或你想学的课程:
我特别决定加入[大学 NLP 实验室],在[真酷教授#1]、多语言语言分析工具和阅读理解的指导下,与[真酷教授#2]一起研究 NLP,为社会造福。我还想将[非常酷的教授#3]在[非常酷的论文]中的工作整合到我对健壮的无监督问答系统的对抗训练的无监督问答的研究中。
我通常为我所有的申请保留相同的前 1.5 页,并为每个特定的项目提供后 0.5 页。
8.写,校对,再写
对我来说,SoP 写作的一个重要步骤是从不同的人那里获得反馈,并一遍又一遍地修改我的文章。
你可以要求阅读你的文章的人的例子有:
- 你的学术顾问/咨询团队:他们通常在校对标准操作程序和给出写作建议方面最有经验
- 你的推荐信作者:他们可能拥有相关领域的专业知识来完全理解你的论文,他们也可能有审查入学标准程序的经验。我的计算机系教授甚至纠正了我的一个技术细节!
- 你的朋友:要么他们以前写过标准操作程序,要么他们和你处境相同,可以分享个人建议
- 你的家人:我的父亲可能不是最有帮助的校对者,他把我送回了“我确信没有进一步的评论。”我的初稿和终稿几乎毫无共同之处。但是你的家人仍然会很高兴阅读你的文章,并给你许多鼓励!
我花了大部分时间编辑我文章的每个细节,直到我没有别的东西可以修改了。此外,我的初稿看起来一点也不像我的终稿。这就是为什么我强烈建议尽快开始制定你的 SoP,以便给其他人留出时间阅读并给你多方面的反馈:)
结尾注释
SoP 一开始可能看起来令人生畏,它确实花费了大量的工作,但是我仍然从编写我的 SoP 中获得了很多乐趣!这是一次很好的锻炼,可以让我明确自己的兴趣,组织自己的经历,并从中吸取经验教训。
这也迫使我精确地反思我的动机,甚至帮助我理解我在研究生学习中真正寻找的是什么。我甚至准备申请一些项目,在那里我甚至获得了推荐信,但是在写我的 SoP 时,我意识到这不是我想要的,我最终放弃了我的申请。
统计(应用时):
- ***学校:*理工学院
- ***学位:*理学学士,数学-计算机科学双学位
- 平均绩点: 4.09/4.0 以上
- GRE: 定量 170/170,口语 169/170,分析写作 5.5/6
- 工作经历: 1 暑期在一家初创企业实习
- ***研究经历:*撰写或发表论文 0 篇
- 课外活动:很多
接受:
- 卡内基梅隆大学(机器学习理学硕士、语言技术硕士)
- 斯坦福大学(计算机科学理学硕士)
- 加州大学柏克莱分校(EECS 工程硕士)
- 哥伦比亚大学(计算机科学硕士)
- 马萨诸塞大学阿姆赫斯特分校(计算机科学硕士)
拒绝:
- 伊利诺伊大学厄巴纳-香槟分校(计算机科学硕士)
- 南加州大学(计算机科学理学硕士)(列入候选名单后被拒)
我有很好的学习成绩,但我主要是因为缺乏工作/研究经验而感到害怕。我认为我的 SoP 和我的推荐信帮助我克服了这个困难,因为它们显示了我对研究生学习的潜力和热情!
如果我错过了任何提示,请告诉我,如果您有任何问题,欢迎联系 Twitter 或 LinkedIn )
附注:我承诺攻读卡内基梅隆大学的语言技术硕士学位,在那里我将从事多语言 NLP 研究!
如何撰写一份成功的数据科学简历
…吸引脸书、谷歌、苹果和微软等公司。
亚历克斯·哈尼在Unsplash【1】上的照片。
目录
- 介绍
- 美学的
- 目标
- 经历
- 技能
- 教育/课外活动
- 摘要
- 参考
介绍
吸引顶级科技公司不仅极其困难,而且令人生畏。然而,我在这里告诉你,你确实可以做到,你可以抓住“ FAAMG ”的眼睛——那就是脸书、亚马逊、苹果、微软和谷歌。这并不是说你改进后的简历不会吸引其他科技公司和创业公司。
这篇文章的主题不是围绕你需要改变你的未来,而是你需要做些什么来更好地推销你的过去。就业市场上有很多合格的数据科学家,有些人可能根本不适合这些公司的职位,因为他们不知所措,不相信自己的工作,更重要的是,不相信自己。对于生活中的大多数事情,自信是关键。更重要的是,提升自信的技能。然而,就你的简历而言,你需要以一种简短而详细的方式来阐述你的技能。当你提到你的过去时,很容易假设雇主会知道你一直在做什么,但你需要专注于你在任何公司都做了什么。
下面,我会给你五种方法来改善你的简历,这样你就可以吸引顶级科技公司。
美学的
让我们从简历的非技术性改进开始。虽然这一点对于你吸引公司关注你的简历来说似乎可以忽略不计,但事实恰恰相反。可以这么说,大多数人点击一篇文章或博客是因为它的主要图片、标题,或者点击一个有着诱人但神秘的缩略图的 YouTube 视频。
简历中你工作的视觉表现不应该被忽视,这是有原因的。
听起来很老套,不合群,脱颖而出。想象一下,你是一名技术招聘人员,你每天会看到几百次同样平淡无奇的黑白墨水简历。什么会先吸引你?这将是你简历的美感、布局和独特之处。就像形成自己的数据科学品牌一样,你应该专注于品牌化你的简历。作为一名雇主,你可以考虑聘用那些在专业但有创意的简历中投入工作的人,而不是其他人,因为这将是他们对你的第一印象。
让我们看看我的。
像这样在网上发布我自己的简历是脆弱和可怕的,我相信它会向你展示你不需要成为一名 UX/用户界面设计师就能获得创造性的成功,但是比别人多一点创造性总是好的——任何人都可以这样做,只需要一点重新安排和组织(或者你可以使用预制的模板——但我更喜欢自制的版本——你的自制版本)。好的,是的,我的这个版本有一点改动(具体来说,就是最近角色的文本和他们各自的公司名称)。然而,它的布局和我最初的简历是一样的,还有标题、主要部分的标题、日期、目标和技能。下面来看看吧。
作者截图和文档[2]。
*那么这份简历有什么了不起的呢?*了解原因的最简单的方法是它很突出。它可能不是最好的或最有创意的,但它是我创造的符合我个性的东西。你想在符合你个性的公司找到一份工作。如果一家公司因为你的简历是蓝色的而不高兴,那么他们可能不适合你——反之亦然,也可以反过来说。当我在 LinkedIn 上发布这份简历,并在他们的网站上申请工作时,我感到紧张、脆弱和与众不同。在提交之前,我问了几个朋友他们的想法,有些人喜欢,有些人不喜欢。
没有完美的简历,但有更好的方式展示你的工作。
我相信我的直觉,想展示我的独创性。就像我的朋友一样,一些公司不喜欢我不拘一格的简历。然而,一些公司喜欢它,并指出(这些公司大多是 FAAMG 公司),以及其他知名的大型科技公司。对我来说,这是值得一提的——这些成功的公司有很多数据科学家想去工作,欣赏创造力和个性——它得到了回报。
有争议的是,我的简历有两页。我已经听过很多次“一页长”的规则,但是只有 1%的雇主会询问简历的长度。如果你拥有它,炫耀它。向雇主展示你为达到这一步付出了多少难以置信的努力。如果他们会看你一整页的简历,他们很可能也会看你 1.68 页的简历。如果没有,那么他们很可能不会给你机会。如果你认为简历需要两页纸,那就写两页。
总而言之,简历的美感在申请过程中会有很大的影响。当然,选择最终取决于你如何设计你的布局和外观。
以下是关于你简历美感的关键提示
* find something unique about you and apply it to your resume* organize the layout in a way that lets the reader focus on each section separately* group your thoughts and work into sections: goal, experiences, skills, education, and extracurricular/awards. * give some breaks between sections so that the eyes can rest (just like how I made these points with a dark background)* tell a story with your layout: what do you want? what have you done? how did you get there?
目标
事实上,我收到了一位前脸书员工的一些建议,每当我更新我的简历或让别人知道他们的简历应该先写什么时,这位员工就一直跟着我。该部分是“目标部分。改善你的简历的一个好方法是包括这个目标部分,因为它向雇主展示了你在寻找什么,几乎回答了面试官经常问的“*你希望在五年内做什么”*的问题。这表明你在提前思考,有计划。此外,这会让招聘人员和/或雇主马上知道你是否合适。
目标部分应该包括你正在寻找的角色,你可以在这里具体说明。所以在我的博客里,我写的是数据科学家,但是你可以写“寻找数据科学中的自然语言处理角色”。确保包括你为什么从事数据科学,以及你想用它做什么。您还可以包含一些重要的链接或用户名,这些链接或用户名指向数据科学中常用的平台。比如我链接了我的 GitHub 和博客用户名。令人惊讶的是,许多雇主指出,很高兴看到他们可以在哪里获得更多与数据科学相关的信息。
以下是改进这一目标部分的主要方法:
- 你想找什么样的角色?
- 你想要什么样的角色?
- 在企业中,你将如何处理这个角色?
- 关于您的数据科学知识的其他链接或信息
经历
简历中最重要的部分是经历部分。当然,尽量避免段落重叠。但是,在必要的地方加入更长的句子。如果你太短,对于第一次看这个项目的人来说,它可能没有那么大的吸引力——额外的几句话就可以了。
当我在简历上的每个公司的经历部分写下要点时,我总是坚持同样的规则。这条规则包括三个简单明了的要点。第一点是概述你使用的工具或编程语言。第二点是突出你实际做了什么。最后,第三点是阐明你所做的结果。那么,总的来说,你用什么来完成这个项目,它的结果是什么?例如,“利用 Jupyter 笔记本中的 Python 创建决策树分类器,帮助将手动分类过程自动化 50% ”。我真的认为这种解释你在每个主要项目中的经历的方法是吸引雇主的最好方法。它会以最快的方式向雇主、潜在的同事和利益相关者展示你对商业问题的影响。这是数据科学的基础;通过使用独特的工具解决复杂的问题来帮助业务。
你应该确保在你的经历部分包含的其他信息是公司、职位和日期。例如,'【2018 年 8 月至今在谷歌的数据科学家。
以下是总结的提升你的经验的关键方法部分:
- 你用了什么?
- 你做了什么?
- 结果如何?
技能
又短又甜。这一部分是显而易见的。您将简单地列出您在数据科学中使用的所有最常用的技能。请记住,您可能希望包括像 Microsoft Office 这样的简单技能,因为,尽管这对您来说似乎是隐含的,但您不应该假设招聘人员已经了解这些知识。同样,根据你想成为的数据科学家的类型,有些技能应该比其他技能更突出。例如,如果你想专注于商业智能和产品管理数据科学,你会突出 SQL、吉拉和 Confluence。相反,如果你想吸引更多的机器学习数据科学,突出像 GCP,气流和 Kubernetes 这样的技能。此外,如果你想更突出一点,确保你的技能看起来很好,有一些模式。
以下是总结的提高技能的关键方法部分:
- 适用于数据科学类型的技能
- 包括非常具体的
- 而且还有一些非常通用的技能
教育/课外活动
与技能部分一样,教育部分不需要很长。包括你的大学本科学位和研究生学位,以及他们的日期,如专业,辅修专业和专业。如果你是一名初级的数据科学家,你可能需要附上你的 GPA。
除了教育,还有课外活动。在这个部分,你还可以包含你的 GitHub 信息或类似的项目共享站点。您还可以概述您的专业、职业数据科学经验之外的关键项目。
如果你没有任何正式的、专业的数据科学经验,那么在“经验”部分列出那些相同的外部数据科学项目。
这些项目的例子包括完成教程、证书、训练营或在线课程(如 Kaggle 数据科学课程)。
以下是总结出的提高你的学历/课外活动的主要方法
- 包括本科和研究生学位(如果适用)
- 保持简洁明了
- 突出你所完成的独特项目和证书
摘要
由paweczerwiński在 Unsplash 上拍摄的照片。
如果您在本文中已经讲到这里,谢谢您。我想给数据科学家最适用、最简单的建议,让他们能在自己梦想的公司找到工作。我在你的简历中加入了美学、目标、经历、技能和教育/课外活动方面的改进。虽然我不能保证找到工作,但我确实认为你会改善你的简历,并有希望吸引你的梦想工作。
再一次,有保留地接受我的建议。我这篇文章的目的不仅是给你简历中这些主要部分的建议,也是给你灵感和动力,让你自己想出新点子。总而言之,你应该专注于做你自己,突出你职业生涯中最自豪的成就(因为你的面试官会挑选你要面试的项目,所以要充分了解它们),找到一些独特和有创意的东西,让你的简历脱颖而出。
我可以证明我的简历截图是我的,并且已经得到了谷歌、苹果、脸书和微软等顶级公司的关注。请记住,还有其他优秀的公司。仅仅因为一家公司不是这些更大的科技公司之一,并不意味着它的价值更低,一家不同的公司可能会更有趣,更有益于体验。最终,在吸引公司之后的下一步是面试。我已经写了几篇关于数据科学和面试过程的文章,如果你想看看,现在就链接一篇,它指的是数据科学和数据分析面试过程中的共同相似之处和不同之处[4]:
面试指南。
towardsdatascience.com](/data-scientist-vs-data-analyst-interview-heres-the-difference-4315f8306ad3)
我希望你觉得我的文章有趣且有用。祝你简历之旅和数据科学事业好运。欢迎在下面评论。感谢您的阅读!
参考
[1]Alex Haney 在 Unsplash 上拍摄的照片,(2019)
[2] M.Przybyla,简历截图,(2020)
[3]2018 年paweczerwi324ski在 Unsplash 上拍摄的照片
[4] M.Przybyla,数据科学家 vs 数据分析师访谈。区别就在这里。(2020 年)
如何用 Pandas 编写所有的 SQL 查询
一个全面的 SQL 到熊猫字典
伊洛娜·弗罗利希在 Unsplash 上的照片
介绍
SQL 之所以如此神奇,是因为它太容易学了——之所以这么容易学,是因为代码语法太直观了。
另一方面,Pandas 就不那么直观了,尤其是如果你像我一样先从 SQL 开始。
就个人而言,我发现真正有帮助的是思考如何在 SQL 中操作我的数据,然后在 Pandas 中复制它。所以,如果你想更精通熊猫,我强烈建议你也采用这种方法。
因此,这篇文章作为一个备忘单,字典,指南,无论你怎么称呼它,以便你在使用熊猫时可以参考。
说到这里,让我们开始吧!
目录
- 选择行
- 组合表格
- 过滤表格
- 排序值
- 聚合函数
1.选择行
SELECT * FROM
如果您想选择整个表格,只需调用表格的名称:
**# SQL**
SELECT * FROM table_df**# Pandas**
table_df
从中选择 a、b
如果要从表格中选择特定的列,请在双括号中列出所需的列:
**# SQL**
SELECT column_a, column_b FROM table_df**# Pandas**
table_df[['column_a', 'column_b']]
选择不同
简单地使用。drop_duplicates() 获取不同的值:
**# SQL**
SELECT DISTINCT column_a FROM table_df**# Pandas**
table_df['column_a'].drop_duplicates()
选择 a 作为 b
如果你想重命名一个列,使用。rename() :
**# SQL**
SELECT column_a as Apple, column_b as Banana FROM table_df**# Pandas**
table_df[['column_a', 'column_b']].rename(columns={'column_a':
'Apple', 'column_b':'Banana'})
选择案例时间
对于 SELECT CASE WHEN 的等效项,可以使用 np.select(),首先指定您的选择以及每个选择的值。
如果您想在每个选项中包含多个条件,请查看本文。
**# SQL**
SELECT CASE WHEN column_a > 30 THEN "Large"
WHEN column_a <= 30 THEN "Small"
END AS Size
FROM table_df**# Pandas**
conditions = [table_df['column_a']>30, table_df['column_b']<=30]
choices = ['Large', 'Small']
table_df['Size'] = np.select(conditions, choices)
2.组合表格
内/左/右连接
简单用。merge() 要连接表,可以使用“how”参数指定是左连接、右连接、内连接还是外连接。
**# SQL**
SELECT * FROM table_1 t1
LEFT JOIN table_2 t1 on t1.lkey = t2.rkey **# Pandas** table_1.merge(table_2, left_on='lkey', right_on='rkey', how='left')
联合所有
只需使用 pd.concat() :
**# SQL** SELECT * FROM table_1UNION ALLSELECT * FROM table_2**# Pandas** final_table = pd.concat([table_1, table_2])
3.过滤表格
选择位置
当像在 SQL 中使用 WHERE 子句一样过滤数据帧时,只需在方括号中定义标准:
**# SQL** SELECT * FROM table_df WHERE column_a = 1**# Pandas** table_df[table_df['column_a'] == 1]
SELECT column_a WHERE column_b
当您想要从表中选择某一列并使用不同的列对其进行过滤时,请遵循以下格式(如果您想要了解更多信息,请查看此链接):
**# SQL** SELECT column_a FROM table_df WHERE column_b = 1**# Pandas** table_df[table_df['column_b']==1]['column_a']
选择地点和
如果要按多个条件进行筛选,只需将每个条件用括号括起来,并用’ & '分隔每个条件。更多的变化,请查看这个链接。
**# SQL** SELECT * FROM table_df WHERE column_a = 1 AND column_b = 2**# Pandas** table_df[(table_df['column_a']==1) & (table_df['column_b']==2)]
选择喜欢的地方
SQL 中 LIKE 的对等词是 .str.contains() 。如果您想应用不区分大小写,只需在参数中添加 case=False(参见这里的)。
**# SQL** SELECT * FROM table_df WHERE column_a LIKE '%ball%'**# Pandas** table_df[table_df['column_a'].str.contains('ball')]
在()中选择 WHERE 列
SQL 中 IN()的对等词是。isin() 。
**# SQL** SELECT * FROM table_df WHERE column_a IN('Canada', 'USA')**# Pandas** table_df[table_df['column_a'].isin(['Canada', 'USA'])]
4.排序值
按一列排序
SQL 中 ORDER BY 的对等词是。sort_values() 。使用’ ascending '参数指定是要按升序还是降序对值进行排序,默认情况下是像 SQL 一样按升序排序。
**# SQL** SELECT * FROM table_df ORDER BY column_a DESC**# Pandas** table_df.sort_values('column_a', ascending=False)
按多列排序
如果要按多列排序,请在括号中列出列,并在括号中的“升序”参数中指定排序方向。请确保遵循您列出的各个列的顺序。
**# SQL** SELECT * FROM table_df ORDER BY column_a DESC, column_b ASC**# Pandas** table_df.sort_values(['column_a', 'column_b'], ascending=[False, True])
5.聚合函数
非重复计数
您会注意到聚合函数的一个常见模式。
要复制 COUNT DISTINCT,只需使用。groupby()和。努尼克()。更多信息请参见此处的:
**# SQL** SELECT column_a, COUNT DISTINCT(ID)
FROM table_df
GROUP BY column_a**# Pandas** table_df.groupby('column_a')['ID'].nunique()
总和
**# SQL** SELECT column_a, SUM(revenue)
FROM table_df
GROUP BY column_a **# Pandas** table_df.groupby(['column_a', 'revenue']).sum()
AVG
**# SQL** SELECT column_a, AVG(revenue)
FROM table_df
GROUP BY column_a**# Pandas** table_df.groupby('column_a')['revenue'].mean()
感谢阅读!
希望这可以作为使用 Pandas 操作数据的有用指南。也不要觉得你必须记住所有这些!当我和熊猫一起工作时,这是我经常想起的事情。
最终,通过足够的练习,你会对熊猫感到更加舒适,并且会充分理解其中的基本机制,而不需要依赖像这样的小抄。
一如既往,我祝你在努力中一切顺利!😃
不确定接下来要读什么?我为你挑选了另一篇文章:
学习熊猫基础知识的最佳资源
towardsdatascience.com](/a-complete-pandas-glossary-for-data-science-a3bdd37febeb)
特伦斯·申
- 如果你喜欢这个, 跟我上 Medium 了解更多
- 关注我Kaggle了解更多内容!
- 我们连线上LinkedIn
- 有兴趣合作?查看我的 网站 。
如何为 algotrade 比特币编写高级趋势跟踪策略
趋势跟踪不再困难
照片由 Katerina Limpitsouni 拍摄
无论是开始算法交易还是盈利,趋势跟踪都是最容易的。在上一篇文章中,我写了一个趋势跟踪策略,通过使用更大的时间框架来确定趋势,甚至提高了它的性能。但这是一个简单的立即进入和立即退出的策略。
本教程的重点是让你从 Jesse 的一些特性开始,这些特性可以帮助你写出你会发现的大多数趋势跟踪策略。这些特征中很少是:
- 分两点退出交易,一点是固定价格,另一点是动态价格。
- 退出一半仓位后将止损更新为盈亏平衡。
- 过滤盈亏比不好的交易。
- 利用事件与交易的生命周期挂钩。
首先,我用make-strategy
命令创建一个新策略:
jesse make-strategy TrendFollowingStrategy
我编辑我的routes.py
文件来使用这个策略,我把时间范围设置为4h
:
然后我打开新创建的策略文件,它看起来像这样:
进入规则
我想去很久,当:
- 我们处于上升趋势中(反之亦然)
- 收盘(当前)蜡烛线触及 50 均线
他们说一张图片抵得上 1000 个单词,所以这里有一张图片显示了我认为的上升趋势:
这就是我所说的当前蜡烛碰到 50 均线的意思(橙色线是 50 均线):
现在让我们为current_candle_touches_long_ema
和trend
写代码:
我用三根均线来确定趋势方向。我返回1
表示上涨趋势,返回-1
表示下跌趋势。current_candle_touches_long_ema
很简单,我只要确保当前蜡烛线的高价大于long_ema
线(周期为 50 的均线)并且当前蜡烛线的低价低于long_ema
线。
设置进场价格和仓位大小
对于多头交易,进场价格将是当前蜡烛线的最高点。止损价格将是当前 ATR 的 3 倍,距离我的进场价格。
在这个策略中,我想一次进场交易,但在两点出场。我将在趋势的前一个高点退出我的前半部分头寸。这里是我所说的上升趋势的高点(蓝线是我的目标):
为了对此进行编码,我首先选择最后 20 根蜡烛线的最高价格。然后返回其中的最大值。
对于头寸规模,我想在每笔交易中用我总资本的 5%来冒险。为了计算qty
,我使用了risk_to_qty
实用程序。
当然,短线交易的情况正好相反。代码如下:
将止损转为盈亏平衡
正如你所看到的,我只是以获利价格退出了我一半的仓位。换句话说,在我的仓位降低后,我想移动我的止损价格以达到盈亏平衡。为了在 Jesse 中编写代码,我将使用内置的 on_reduced_position 方法。
更新self.stop_loss
是我告诉杰西更新我的止损单所需要做的。Jesse 自动选择它,取消之前的止损单,并提交新的止损单。这再简单不过了!
要了解关于事件的更多信息并查看 Jesse 中所有可用事件方法的列表,请务必阅读其文档。
动态退出我交易的后半部分
对于这个策略,我打算在动态的情况下退出我的后半部分头寸。这种情况背后的想法是,当价格高度超买,即将进行严重的修正时退出。用 quant 的语言来说,我想在 RSI 指标达到 80 以上的时候退出。
首先,我将使用内置的update_position()
方法来编写我的逻辑。只有当我们有一个未结头寸时,这个方法才会在每根新蜡烛线后执行。因此,它用于更新位置。也就是说我们不需要检查这个职位是否空缺。
这里要考虑的下一件事是,我只想退出我的后半部分头寸。换句话说,我想平仓,如果它已经减少。检查我的头寸是否已经减少的最简单的方法是使用内置的 is_reduced 属性和清算()方法。
使用过滤器
到目前为止,我的策略看起来不错,让我们进行一次回溯测试,看看效果如何:
jesse backtest 2019-01-01 2020-05-01
经过大约 4%的回溯测试后,我得到一个错误:
Uncaught Exception: InvalidStrategy: take-profit(3601.6) must be below entry-price(3601.6) in a short position
错误是试图告诉我们,在某一点上,我们的策略的获利和进场价格相等(3601.6 美元),这是不可接受的。这是一个很难调试的问题,但是在编写了最初的几个策略之后,你会很擅长和 Jesse 一起调试。
为了解释为什么会出现这个问题,我们需要再看一下获利和进场交易:
这个错误告诉我们,进场和获利在某些时候是相同的。这意味着,在这一点上,当前的蜡烛线是过去 20 根棒线中最高的。这不是我们在这个策略中想要的交易类型。
我们可以通过在我们的should_long
方法中使用一些肮脏的 if-else 语句,或者通过使用一个专为这类情况设计的过滤器来防止这种情况发生。
过滤器只是一个返回布尔值的函数。通过返回一个True
值来传递一个过滤器,反之亦然。我定义了一个过滤器,并命名为reward_to_risk_filter
。这个名字可以是任何东西,但是用单词filter
开始或结束一个过滤方法的名字通常是一个好的习惯。这个过滤器的工作是确保我们试图进入的交易是值得的。
在这一点上,杰西仍然不知道reward_to_risk_filter()
是一个过滤器。为了让它识别我的过滤器,我需要将它添加到filters()
方法中,这是一个返回 Python 列表的内置方法:
现在我将把reward_to_risk_filter
作为一个**变量添加到返回列表中。**这意味着它的末尾不能有括号:
现在让我们再执行一次回溯测试:
jesse backtest 2019-01-01 2020-05-01
这次一切顺利。
结论
你的策略越简单,就越容易调试它们,甚至随着时间的推移改进它们。
和杰西一起写策略就像手动交易你的策略一样简单。所以下一次你在交易书上或者交易大师那里发现一个策略时,就写下代码,并进行回溯测试。
为了获得我未来的作品和产品,请务必订阅杰西的时事通讯,并查看论坛与像你我这样的量化分析师讨论算法交易。
注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
如何写一篇精彩的自述
一个全面的指南写自述,脱颖而出,使人去哇!
照片由 Pixabay 拍摄
如果你很急,只想让模板跳到底部(不酷)。
其余的酷人准备好迈出成为自述大师的第一步吧!(绝对不是 clickbait)。
你刚刚创建了这个很棒的项目,并在 GitHub 上分享了它。你认为现在你可以坐以待毙,等着世界告诉你你的项目有多酷。毕竟,在过去的一个月里,你在这个极具挑战性的项目上不知疲倦地工作,对吗?
好吧,让我们后退一步,从检查你的项目的开发者或用户的角度来看。尽管你知道你的项目有多酷,知道它将如何解决一个尚未解决的紧迫问题(直到你出现),但这个人会看着你的项目,想知道你到底做了什么。
如果没有人不知道如何使用你的软件,那一定是发生了非常糟糕的事情。
照片来自 imgflip
如果人们不知道你的软件是做什么的,那么他们不会使用它或为它做贡献,他们很可能会在开源软件的海洋中找到更清晰和简洁的东西。
这就是自述文件的用武之地!
一份好的自述文件就像是你项目的门面。这是人们在你的项目中看到的第一样东西,它给他们一个非常简短的对你的软件的介绍。
自述开始来自我的NSFW滤镜项目
一个好看且有帮助的自述文件可以使您的项目脱颖而出,并吸引开发人员社区的注意。
这将有助于他们理解你的项目,他们如何让项目运转起来,以及为什么他们应该做出贡献。
“哇,老兄!说得好!如果你知道这么多东西,为什么不告诉我们怎么写呢…”
嘿,我不能告诉你有一套具体的规则,你应该遵守这些规则,不要为了一个好的自述而摇摆不定。
它不那样工作。
我将分享我如何为我的开源项目写自述文件,以及你在为你的项目写自述文件时应该考虑的事情,你将(希望)能够获得一些见解。
还有,记住你不会一天就成为自述大师。像所有的事情一样,需要练习。
我为开源做贡献已经有一段时间了,我注意到所有伟大的项目都有一个棒极了的自述文件。
您进入了项目页面,几分钟后您就可以启动并运行您的项目版本。
有许多贡献者,许多请求,更新版本被频繁发布,它们都有一个令人敬畏的自述文件的共同因素。
一个新的开发者将能够找到所有的细节开始像安装说明和贡献指南。
一个新用户将能够通过信息截图和演示找到这个项目是如何被使用的。
“我没时间说这个,给我看看自述文件吧!”
好吧,好吧,好吧(抱歉我走得有点麦康纳)。
这里是我的项目 NSFW 滤镜 的自述文件。我认为这是我写的最好的自述。
从网站过滤 NSFW 图片的网络扩展。它使用 TensorFlow JS-一个机器学习框架-来…
github.com](https://github.com/navendu-pottekkat/nsfw-filter)
我将浏览自述文件的不同部分,我认为对每个自述文件都是必不可少的。
这里是本例中使用的自述文件的链接。您还可以找到一个 模板自述文件,您可以直接将其复制并粘贴到您的项目中。
[## navendu-pottekkat/awesome-readme
项目标题应该不言自明,尽量不要弄得拗口。(尽管存在例外情况……
github.com](https://github.com/navendu-pottekkat/awesome-readme/blob/master/README.md)
好吧,那就结束了。
我用这些来自自述老师 ( 新推特手柄预警)的临别赠言(智慧)告别我的蚂蚱!)。
照片来自 imgflip
如何撰写和发表研究论文
我希望在写和发表我的研究论文之前阅读的文章
你目前正在攻读博士学位。或者将来有兴趣做。你可能即将发表一篇科学论文,或者只是对发表你的作品感到好奇。
在这个博客里,我写了我写论文的经历。我与你分享我在科研生涯中学到的技巧和经验。我在顶级 IEEE 会议和期刊上写了+7 篇文章(IEEE Transaction on Image Processing)(EUS ipco,WOSSPA,GRETSI,GDR-ISIS,…)。我还撰写了一篇发表在天文学&天体物理学的期刊论文。你可以在我的谷歌学术个人资料或 ResearchGate 个人资料中找到我的出版物列表。
我把这个博客分成两个不同的类别,没有特定的顺序:
- 与出版物需要做的事情相关的非技术部分
- 与研究相关的技术部分
🅛🅔🅣’🅢 🅖🅞
非技术部分
📝正确的纸张格式
你需要为你的论文选择合适的格式。出版物有很多种,如会议或期刊、信件、评论、会议或期刊文章。根据您的研究阶段或您正在展示的信息水平,其中一个可能比另一个更适合您的工作,以评估您想要传达的信息并选择您的格式。
🔎选择会议
如果你想提交一份会议论文,你需要选择哪一种信心,要知道这是一个你必须参加的活动。有很多会议,取决于你的研究领域,每个会议都有自己的地点和日期。所以一定要了解你所在领域的顶级会议,这很重要。如果你是博士生,不要犹豫和你的导师交流,他们通常已经有了入围的会议名单。
细节很重要
一旦你选择了会议,你需要注意并阅读关于截止日期、地点、作者指南、电话和提交指南以及价格的所有细节。
⚠️Yes,你必须付费才能在同行评议的期刊/会议上发表你的作品。有一个免费的出版物平台(像 Medium),或者像 arXiv 这样的开源平台,但是没有同行评审。当然,如果是会议论文,不要忘记支付出版费和注册费+酒店。
⏳最后期限
关于截止日期的重要几点,首先,你不想错过!。其次,很明显,你想在截止日期前提交。通常情况下,作者会对提交的论文进行修改,这种情况经常发生,或者更新内容。知道你有可能在提交截止日期前对提交的版本进行修改。
💡你越早提交论文越好,给自己一些安慰,不要等到最后一天才提交,以免出现意外。
纸质 PDF 模板套件
大多数会议和期刊都提供模板工具包来生成最终的 PDF 论文。它通常以两种格式提出:Latex 的 Microsoft word。下载模板工具包并开始编辑内容。我确保你尊重格式的规则(大小,字体,警察,引文,表格,…)。
编辑工具
我真的推荐使用 latex,尽管与 Microsoft word 相比它很痛苦,但是相信我,使用 latex 生成的 PDF 质量非常好。
💡我建议用 TexStudio 来编辑你的论文,在我看来这是最好的之一。
TexStudio
要准备的其他材料
被接受的会议论文必须在会议当天提交。一般来说,有两种方式来展示你的作品:
1-展示海报
或者在观众面前演讲
在这两种情况下,你都必须准备一份额外的材料来总结你的工作,可以是海报或幻灯片,这是会议委员会所做的决定。
期刊论文除外
关于期刊论文,程序略有不同。一般来说,没有事件发生,所以没有截止日期,也没有事件日期。你可以随时提交期刊论文。只要确保你的研究没有过时。
技术部分
🚀开始写作之前
写作前问一些问题会帮助你理解你的工作,并更好地向他人解释,例如
- 这是一个重要的问题吗?
- 收集和分析的数据对更广泛的社区有意义吗?
- 过去做了什么?
- 解释为什么解决它很重要?
首先,你需要选择一个你想解决的问题。你一定是具体的,不然干嘛还要费神去读博。!严肃地说,不要在别人已经解决的特定问题上工作。
📎文献综述
了解其他研究人员为解决你想要解决的问题做了什么是关键。以前的方法有什么优势和局限性,这在你的步骤中非常重要和关键,因为对另一个人来说,你的研究是相关的,你需要向读者或负责你工作的大学委员会展示和说服你的贡献是值得的,你正在提议可变的研究
⚠️为了这一步,拖延症将试图成为你最亲密的朋友。只是意识到这一点,不接受它作为朋友。
💡我建议用门德利来管理你的推荐人。简单易用,您可以在手机、PC 或浏览器上使用它。
门德利
这一步将定义你工作的基础,所以你将从实施一些方法开始,并了解已经做了什么,有什么限制,正如我之前所说的,从那时起你将发现还没有做什么,有时在其他研究中, 研究人员强调了他们想做什么和他们不能做什么。也许这会给你一个想法,从经验中开始,那些掌握了这一步的人会很容易进入下一步,那些没有掌握的人会很困难,我们将不得不在他们论文的结尾做这项工作。
🔧发展手稿:结果和写论文哪个更重要?
从写论文到出结果
你可以从写论文开始,随着研究的深入,在空白处填入内容。在这种情况下,这篇论文将推动你的研究,推动你的工作向前发展,这是一种以英语为母语的方法。
填空让你思考题目,问自己一些问题,比如我想说的题目是什么?以前做过什么?我应该提出哪种策略或方法?诸如此类。
从结果到写论文
或者你可以遵循法语的方法,这种方法包括首先关注结果,然后写论文。这种方法最适用于已经了解主题并且问题已经解决的人。一旦有了结果,他就可以开始写论文了。下一个任务将是证明一个论点,并试图融入文献中的研究。
这里没有好的或错误的策略,它们都非常有效,只需选择一种方法并坚持下去。
💡如果你是博士。学生,不要犹豫和你的导师讨论这个问题。他们会指导你,带你完成博士学位。
📌从哪里开始写?
科技文章通常遵循以下格式:
- 摘要
- 简介
- 之前的研究
- 问题公式化
- 模型或方法和结果
- 结论
- 参考文献
- 致谢
你论文的每一部分在向读者解释为什么你的研究提出了一个新的重要问题,以前已经做了什么,以及你的研究如何实质性地推进你的领域中扮演着不同的角色。
💡我建议你按照这个顺序:先把问题公式化,然后写你用来解决问题的方法,接着是结果。接下来,你回到引言,然后是你的结论。摘要应该写在最后。
在你起草完所有的章节后,你应该重温你的标题和作者列表,以确保它准确地代表了你的最终作品。致谢和参考文献可以在文章写完后完成。
🗣投稿& 同行评审
与你的合作者一起重复修改和更正。迭代越多越好。随着时间的推移,你会收敛到论文的最终版本。此外,让你的朋友或同事审阅论文。可能会有一些你看不到的错误。你擅长提交论文。
💡记住,在提交论文之前,一定要和你的合作者反复讨论。你必须得到他们的同意,以避免可能发生的误解或混乱。
结论和带走
从我的个人经验来看,我可以告诉你,在写作时凌乱是正常的,知道那是可以的,那是不可避免的。不要不知所措。保持一致,不要忘记给自己一个喘息的机会🙂。你需要在你的写作程序中建立足够的秩序,以便能够向前推进。
好了,我希望你能从这篇博客中获得一些价值,并在你的下一篇论文中受益。💯
不溅
下一步做什么 ❓
- 请在评论区告诉我你的想法,或者直接在 LinkedIn 上给我发消息。
- 你采取了什么方法?
- 什么对你最有效?
如何在介质上编写和渲染 LaTeX 数学公式
在这篇文章中,我们列出了一些在介质上书写和可视化数学公式的方法:LaTeX 到 image,unicode 转换,浏览器插件等。
安托万·道特里在 Unsplash 上拍摄的照片
每天,许多从业者通过在媒体上创建内容来分享技术教程和发现。然而,张贴带有数学公式的文章(例如用 LaTeX 写的方程式)是一件困难的事情,因为它在媒体上不受支持。最常见的解决方法是将你的公式转换成图片并添加到文章中。你可以对一个渲染的 PDF 文件进行截图,或者使用在线 LaTeX 编辑器,比如 CodeCogs 。
图片作者。在线 LaTeX 编辑器。
包含本文所附公式的图像将显示为:
这是在 Medium 上发布时添加数学公式的最简单的策略,但它不灵活,并且不适用于内嵌方程。
类似的方法包括使用数学公式创建 Jupyter 笔记本降价,并将笔记本上传到GitHub Gist。
图片作者。GitHub Gist 包含一个准备嵌入介质的乳胶配方。
然后,复制介质上的共享链接,结果是:
作者笔记。包含 LaTeX 公式的嵌入式 GitHub gist 示例。
老实说,这不是很花哨。
另一种在介质上添加乳胶配方的方法是使用 TeX 到 Unicode Chrome Addon 到转换乳胶代码到 Unicode 。一旦安装了插件,只需选择你想转换的 LaTeX 代码,例如
\alpha : \mathbb{R} \to \mathbb{R}
按 Alt+W(您可以在配置中更改快捷键),您应该会得到等式的 unicode 版本:
α : ℝ → ℝ
这种方法不依赖于图像或嵌入对象,它可以内联工作,但在字符和布局转换方面也有限制。例如,上面的例子
(\cos x + \sin x)^2 =
\underbrace{\cos^2 x + \sin^2 x}_{1} +
\overbrace{2 \sin x \cos x}^{\sin 2x}
被转换成
(\cos x + \sin x)² =
\underbrace{\cos² x + \sin² x}₁ +
\overbrace{2 \sin x \cos x}^{\sin 2x}
当公式有点复杂时不是很有用。
最后一种在媒体上呈现数学公式的方法需要在创作者和读者的浏览器上都安装一个 Chome addon 。该插件被称为数学无处不在,它应该渲染任何页面上的每一个 MathML/LaTeX 公式,也在媒体之外。在编辑过程中,你只需要把你的公式放在适当的分隔符中,如美元符号(插件应该关闭),在阅读过程中,一旦激活插件,方程将被转换。
公式
应正确呈现:
(cosx+sinx)2=cos2x+sin2x+2sinxcosx(cosx+sinx)2=cos2x+sin2x+2sinxcosx(\cos x+\辛 x)2=\cos2 x+\sin^2 x+2 \辛 x \科斯 x
像α:R→Rα:R→R \ alpha:\ mathbb { R } \ to \ mathbb { R }这样的内联公式也应该可以工作。这种方法的缺点是需要读者安装插件(只有第一次)。当然,我们可以像这样在帖子的开头插入一个善意的提醒:
这个帖子包含乳胶公式。为了正确渲染它们,安装数学任意位置插件并激活它。
你知道在介质上添加数学公式的其他方法吗?请在评论中告诉我!
参考资料:
如何像软件工程师一样写文章
有效和高效写作的缺失手册
阿里安·达尔维什在 Unsplash 上拍摄的照片
写一篇有效、高效的文章意味着什么?根据剑桥词典有两个定义:
1。高效:充分利用时间、材料或能源等资源,不浪费任何资源。
2。有效的:产生预期的结果,或(指人)有技能或有能力做好某事。
换句话说,写一篇有效的文章意味着用正确的方式写出正确的文章。鉴于我有计算机科学的背景,这听起来对我来说很熟悉。
这些定义听起来类似于您在软件工程领域经常听到的两个术语,即:
1.验证:对一个系统的测试,以证明它满足其开发的特定阶段的所有规定要求。
2.验证:确保最终产品利益相关者的真实需求和期望得到满足的活动。
简单来说,验证是关于以正确的方式构建产品,而验证是关于构建正确的产品。
我越想这些相似之处,就越想构建一个软件和写一篇文章之间的其他相似之处。
计算机科学只不过是处理和解决问题的科学。算法只不过是一个配方。这个提示列表可以被看作是一个简单的算法,用来写出有效且高效的文章。或者,如果你想从软件工程师的角度来看,只需要一个清单来验证你的文章。
本质上,这篇文章只是一个微弱的尝试,来帮助自己成为一个更好的作家。帮助我自己处理混乱的过程,不要迷失在细节中而忽略了大局。这是一个非详尽的通用提示列表,您不必一步一步地遵循。你甚至不需要同意他们所有人的观点!只拿你需要的。
虽然我写这篇文章只是为了自己,但我希望其他人也能从中受益。
1.有主意了
在 Unsplash 上由 Majharul Islam 拍摄的照片
"玫瑰始于花蕾,鸟儿始于蛋,森林始于种子。"马特肖纳·德里瓦约
一切从一个想法开始。不管它有多小,也不管它是关于什么的。只要你觉得值得分享。它可以是一个教程,一个个人故事,一篇书评,或者任何你喜欢写的东西。不管是什么,你应该有一种强烈的冲动把它从你的胸中拿出来。
我通常一周有几十个想法,但只有几个能坚持下来。如果某个想法在我的脑海中反复出现,我知道我必须采取行动。
你不知道吗?那你希望看到的目前不存在的是什么呢?或者你的朋友或家人有什么样的问题你可以解决?对开发软件有效的问题同样适用于写文章。只要你的想法解决了某人的问题,你就在正确的轨道上。哪怕只是你自己的问题。
以这篇文章为例。它的存在仅仅是因为我想有一种指南或清单,可以用于我未来的文章。然后我想其他人也可以从中获利。这就是了。
2.做你的研究
“从别人的错误中吸取教训。你不可能活得足够长,让它们都是你自己做的。”―埃莉诺·罗斯福
每当一个特定的想法打动我时,我都很兴奋,并认为世界上还没有人写过这个特定的主题。或者曾经写过这样的软件。
我最近有了一个想法,用 Python 为不同种类的媒体类型编写一个并行的 web scraper。在快速的网络搜索之后,我发现我的想法已经被很多人关注了。可能比我聪明得多的人。如果你曾经遇到过类似的情况,那么你可能也会感到气馁。
但你不应该,因为这并不意味着它的结束。这种情况一直都在发生。只能说明你遇到了现实世界的问题。一个值得已经尝试解决它的人花时间去解决的问题。这并不意味着他们的解决方案有任何好处。
脸书逐渐取代了 MySpace,尽管他们都面临着同样的问题。
根据维基百科,
市场营销和战略管理中的竞争对手分析是对当前和潜在竞争对手的优势和劣势的评估。
把你的想法拿出来,看看其他人是否已经尝试过解决它。他们的解决方案好吗?从他们的错误中吸取教训,并使之变得更好。汇总他们的发现,对你最初的想法有新的见解。也许你最初的想法会演变成不同的东西。更好的东西。
用一个快速的研究会议来验证你的想法。你花在早期研究阶段的时间是一项伟大的投资,因为建造一个没人想要的东西是世界上最糟糕的感觉。
打造一个人们愿意为之付费的产品。在中等文章的具体情况下,人们不是直接用他们的钱而是用他们的阅读时间支付给你。人们想要有价值的信息作为回报。
3.创造价值
“努力不要成为一个成功的人,而是成为一个有价值的人。看看周围的人是如何想从生活中获得比他们投入更多的东西。一个有价值的人给予的会比他得到的多。”——阿尔伯特·爱因斯坦
不管你的想法是独一无二的还是其他人已经有了相同的想法。重要的是你的产品为用户创造价值。
当谈到媒体文章时,你必须问自己这样一个问题:有人真的会通过阅读这篇文章有所收获吗?
不要模仿别人,但也不要重新发明轮子。汇总你的研究成果,并以此为基础。让它变得更好!
读者应该渴望读到你的文章,直到最后。和他们一起玩 FOMO(害怕错过)。得到一些好的报价。人们喜欢学习新的东西。如果他们能在下一次家庭聚会上使用这些新知识来传播一些智慧,那就更好了。我在这篇文章中也是这样做的。
在增加价值的方式上要有创造性。以第 2 点中的并行 web scraper 为例。大部分提到的网页抓取库都只是命令行工具。然而,当我使用这些库来实现一个更大的、对最终客户来说易于使用的在线平台时,我突然创造了额外的价值。试着在你的文章中做同样的事情,要有创造性。
此外,想想你的产品的寿命。一个月后会过时还是一年后仍有价值?
4.第一个原型
“好故事不是写出来的。它们被重写了。” —菲利斯·惠特尼
第一个原型类似于草稿,可以用于许多目的。这可能类似于产品设计中的探索性原型设计,在创造东西的同时发现新的想法。这可能是一个概念的证明,或者是一个最低可行的产品,让你自己看看当你的想法实现时,它是否仍然有意义。
对于其他人来说,这只是为了看到他们的想法写在一个地方,以获得更清晰的画面。写下一些东西会激活不同的神经通路,而不仅仅是思考。
不管它是什么,大多数时候它都是一堆没人需要看到的脏东西。这很好。一个制陶师不是从一个成品花瓶开始,而是从一堆乱七八糟的粘土开始。你也应该这样做。允许自己写非常糟糕的内容。
每当我有一个无法摆脱的应用程序的想法时,我通常会创建一个 Github 库,并创建一个非常小的原型和一些注释。我写糟糕的代码,只是试图让它以某种方式工作。
对于一篇文章,我通常会做一些笔记,或者只是在草稿模式下写一篇中等大小的文章,然后开始写作。我的第一个笔记包括要点,例句,标题和副标题,如何组织文章,我的文章的目标是什么。这是一个烂摊子。
你可以自己选择如何完成初稿。有些人喜欢用演绎的方式来处理它,这意味着你要从更一般的到更具体的。其他人更喜欢以归纳的方式工作,这是相反的方式。你从细节转移到更一般的东西。或者两者的混合。你觉得怎样都行。
我喜欢用一个 25 分钟的番茄时段来写我的初稿,因为这让我有时间压力。在时间压力下工作支持两个重要的法则。
帕金森定律 陈述如下:
“工作扩大以填补完成它的时间”——西里尔·诺斯古德·帕金森
另一方面, 帕累托法则 (也称为 80/20 法则)指出:
“对许多事件来说,大约 80%的结果来自 20%的原因.”—维尔弗雷多·帕累托
遵循这两条定律意味着我只有 25 分钟的时间来想出有价值的内容。因为我只有 25 分钟的时间,所以我更有可能只写下重要的 20%的想法,而这些想法可能对最终的产品有 80%的贡献。
此外,我不太可能走神,因为时间紧迫,我心中有一个明确的目标。
5.设定 SMART 目标
亚历山大·席默克在 Unsplash 上拍摄的照片
“如果你不能衡量它,你就不能改善它。” —彼得·德鲁克
目标很重要。这没什么新鲜的。一个目标可以是:
“我想更好地学习编程!”
这是一个很好的目标,但它相当宽泛和不明确。你想怎么变好?需要多长时间?具体想改善什么?你想学习更多关于数据结构的知识吗?你应该有智能目标。 SMART 是项目管理领域经常使用的缩写词,代表:
- 具体的:你的目标不应该太笼统。不然你想怎么确定你达到目标的点呢?你的目标应该是具体的,你应该选择一个具体的衡量标准,告诉你什么时候你真正达到了目标。
- 可衡量的:你应该能够跟踪和量化你目标的进展。这也增加了动力,因为你现在有了一个工具来反馈自己的进展。
- 可实现的:评估你自己目前的能力,检查你是否能以目前的技能达到你的目标。尽量现实一点。少做多做是一个原则,这个原则对许多人来说是有效的,可以一步一步实现小目标。
- 相关:你的目标有助于更高的目标吗?是不是一个更大问题的子解决方案?它在多大程度上帮助了你?会带来更多收入吗?
- 有时间限制的:有时间限制的目标有助于你按计划进行。给自己设定一个截止日期可以帮助你以更有效的方式实现目标。达到一个目标是伟大的,但如果花的时间太长就不是了。
你每设定一个目标,它都应该具备这五个特征。使用任何你认为合适的工具。用一张纸写下 SMART 目标的五个栏目。你甚至可以使用 Scrum 或看板板,如 Trello 来帮助你。在开始写文章或软件产品之前,写下 SMART 目标。从长远来看,这对你有好处。
快速达成目标是好事。快速达到正确的目标更好。
6.结构
Jason Abdilla 在 Unsplash 上拍摄的照片
“给我六个小时砍树,我会用前四个小时磨利斧头。”—亚伯拉罕·林肯
不管你想创作的是一篇文章还是一个软件产品,它们都应该有一个合适的结构和基础。这几乎就像盖房子一样。你从地基开始,而不是屋顶。
以我的人体素描为例。如你所见,我不是专业艺术家,但这有助于解释我所追求的类比。
我自己的男性人体素描
素描在早期绘画阶段很重要。素描有助于获得正确的比例。你可以添加尽可能多的细节,试图掩盖潜在的错误,但所有的细节都无法弥补糟糕的比例。
同样的原则也适用于软件开发。你可以实现一个看起来很棒的软件,但是如果功能不正确,你不能用闪亮的按钮来弥补。
写作也不例外,在添加细节之前,先弄清楚结构和基础,可以节省你大量的时间。你的想法应该符合逻辑。一步接一步。一点一点地积累,并有一个要点要传达。
通过介绍问题或理解文章所必需的任何东西来提供一些背景。之后,提供一个问题的解决方案或主要内容。牵着读者的手,做一个引路人。
我通常根据章节和标题来考虑文章结构。我创建章节,直到我认为我的文章的每个方面都涵盖了。所有部分的总和应该产生一个连贯的乘积。只有在那之后,我才试着用细节来填充这些部分。
7.了解你的目标受众
埃尔蒂·梅绍在 Unsplash 上拍摄的照片
“总是尽可能让观众痛苦。”—阿尔弗雷德·希区柯克
你不必照字面理解希区柯克的建议,吓跑你的用户和读者。除非这就是他们想要的。这是这里的主要信息。
买阿尔弗雷德·希区柯克或斯蒂芬·金的书的人脑子里都有某些假设。他们想通过害怕来娱乐。他们想要恐怖片、惊悚片或两者兼而有之,而不是爱情片。
你必须为合适的人制造合适的产品。为了制造合适的产品,你必须了解客户的需求和问题。你必须了解你的观众。你为谁写作?这是一个类似于软件验证的概念,定义如下:
“确保最终产品利益相关者的真正需求和期望得到满足的活动.”
软件验证试图回答这个问题:我正在构建正确的产品吗?
当你开始写文章时,你可以问自己几个关于目标读者的问题,比如:
- 他们想要艰难、无聊的事实,还是情感的过山车?
- 我写作的目的是什么?
- 根据我的听众的技能,内容是否合适?是不是太技术化了?是不是技术不够?
- 我这篇文章的要点是什么?这对我的观众有多大帮助?
试着从读者的角度看问题。孙子的一句名言说:
“知己知彼,百战不殆。如果你了解自己但不了解敌人,那么每一次胜利都会让你遭受失败。不知己知彼,百战不殆。”——孙子
虽然读者和用户不是你的敌人…在大多数情况下…你可以从这句话中学到很多。
当你为一个不知名的观众写一些你自己都不相信自己的东西时,你肯定注定会失败。当你写了一些伟大的东西,但你不知道是为了谁,这只是一个赌博,如果你的文章会成为一个成功。最后,当你为合适的人写好内容时,你会极大地增加你的机会。
再说一次,建造没人想要的东西是世界上最糟糕的感觉。
8.紫色的母牛
照片由 Unsplash 上的 Stijn te Strake 拍摄
“成功的关键是找到一种脱颖而出的方法——成为单色荷斯坦奶牛中的紫色奶牛。”——塞思·戈丁
想象一下,你开着车,经过一片满是奶牛的田野。它们可能大小不同,可能有不同的黑白图案。这是一个常见的景象,你甚至不会给他们太多的注意力。他们中没有一个是鹤立鸡群的。然而,那是你想要实现的。鹤立鸡群。你想成为每个人都立即注意到的紫色奶牛。
紫牛的例子是一个常见的商业类比。针对媒体,有不同的方法来解决引起注意的问题,例如:
- 引人入胜的标题和副标题
- “踢球者”
- 为搜索引擎优化定制标题和副标题
- 从 Unsplash 、 Pexels 、 Burst 、 The Stocks 、 Pixabay 等网站免费获取你的精选图片。
用户通常只需要一秒钟来决定他们是否要点击你的文章。一个好的标题和特色图片当然会有所帮助。
同样的原则也适用于 App-store 中的应用。你必须想出有创意的方法来脱颖而出。做紫牛。
9.分步解决
卡洛斯·伊瓦涅斯在 Unsplash 上的照片
“分而治之。”—朱利叶斯·凯撒
Julius Caesar 的这句名言也适用于计算机科学领域。分而治之可以作为一种算法设计范例
该算法的工作原理是递归地将一个问题分解成两个或更多相同或相关类型的子问题,直到这些子问题变得足够简单,可以直接解决。然后将子问题的解决方案组合起来,给出原问题的解决方案。
如果你把一篇文章当成一个你想要解决的更大的问题,那么把文章分成更小的子问题是有意义的。
一方面,这为你自己创造了动力和动力,因为你现在有了小而容易的子问题,而不是一个大的、整体的问题。你可以将每个子问题与你想要达到的里程碑联系起来,这样你就创造了一种衡量你进步的方式。
另一方面,将文章分成更小的子问题也可以意味着为读者在视觉上划分文章。大多数情况下,如果读者发现文章中间没有什么停顿,他们会觉得读起来更容易。你可以使用链接、图片、视频或任何你喜欢的东西。
以这篇文章为例。我用图片把文章分成了每一部分。
10.整体情况
Lukasz Szmigiel 在 Unsplash 上拍摄的照片
“如果你花一生的时间去分析每一次遭遇,你只会看到树,而看不到森林。”香农·阿尔德
你是否迷失在细节中?你在一个句子上写了将近十分钟吗?你难道看不见森林吗?
你必须不时后退一步,从整体上看待这个问题。如果细节无助于大局,即主要问题,那么细节就毫无意义。
休息一会儿,想一想你真正想用你的产品达到什么目的。你目前的活动对产品的贡献有多大?值得吗?
11.不要做一个完美主义者
布雷特·乔丹在 Unsplash 上的照片
“从根本上说,完美主义并不是对一丝不苟的热爱。是关于恐惧。害怕犯错。怕让别人失望。害怕失败。怕成功。”迈克尔·劳
有一个关于陶瓷班的好故事,证明了数量重于质量。
最高质量的作品都是由被评定数量的小组制作的。看起来,当“数量”组忙于大量的工作,并从他们的错误中学习时,“质量”组却坐在那里理论完美,最终他们的努力只剩下浮夸的理论和一堆死粘土。
不要试图想出一个完美的产品,也不要浪费太多时间对你的产品进行理论化。熟能生巧。大师失败的次数比初学者尝试的次数还要多。
写下最少的内容来表达你的观点。你可以创建一个临时附录部分,附加内容可能是也可能不是你最终文章的一部分。
记住技巧 4 中的帕累托原则:
“对许多事件来说,大约 80%的结果来自 20%的原因.”—维尔弗雷多·帕累托
当你认为你的文章差不多准备好了,就发表吧。不要浪费太多时间润色,因为你可能会花 80%的时间把文章的最后 20%写得恰到好处。你仍然可以在以后改正小错误,并采纳读者的反馈。
完成比完美更好。
12.让它成为一次愉快的经历
他们可能会忘记你说过的话,但他们不会忘记你带给他们的感受卡尔·布埃希纳
人类是有情感的生物。不可否认。你的文章内容也应该传达情感,使之成为一种愉快的体验。
许多软件公司都有人负责用户体验(UX) :
用户体验 ( UX )是一个人对使用某个特定产品、系统或服务的情绪和态度。它包括人机交互和产品所有权的实用、体验、情感、有意义和有价值的方面。
关于如何获得愉快的用户体验,没有固定的规则。这可能是一个快速的加载时间,令人鼓舞的消息,漂亮的视觉效果。你的想象力是极限。
对于中型文章,您可以尝试使用 Medium 提供的几种格式化选项。使用文体特征,看看它们是否能让你的文章更有趣。
在我的一篇关于如何阅读科学论文的文章中,我试着非常鼓励你,因为我知道面对你的第一篇研究论文是多么困难和令人畏惧。
要有创造性,把读者想象成一个你想以善意的方式接近的好朋友。
13.简单点,笨蛋
“一切都应该尽可能简单,但不能更简单。”——阿尔伯特·爱因斯坦
接吻原则是“保持简单,笨蛋”的首字母缩写。KISS 原则不仅适用于软件设计,也适用于写作。尽量使用简单的句子,让你的内容容易消化。不要把事情复杂化。乔希·考夫曼曾经说过:
“系统越复杂,运行时间越长,就越有可能出现重大故障。”
如果你写的句子过于复杂,并且包含大量重复,你的读者会失去兴趣。要精确。
14.工具
Cesar Carlevarino Aragon 在 Unsplash 拍摄的照片
“这可能不是问题所在。相反,问题可能是我用来尝试解决问题的工具。”克雷格·劳恩斯布鲁
没有她/他的工具,程序员什么都不是。程序员使用 ide 让他们的生活变得更简单,他们喜欢自动化。而且,大部分程序员都很懒。我也不例外。
一个作家也可以受益于各种工具,以提高效率。你可以使用像这样的拼写检查器。你可以在文章中添加视觉辅助来支持你的内容。添加图像或视频,但要确保你没有侵犯任何版权。
15.给予,它就会给你
“因为我们正是在给予中获得的。”—弗朗西斯(阿西西的)
存在这样一个奇怪的普遍规律:慷慨付出的人得到的更多。我在这篇文章中遵循了这个原则,链接了我认为有帮助的其他文章。我使用推荐人,并在该表扬的地方给予表扬。
说到编程,同样的原则也适用于开源项目。乍一看,你似乎是免费工作的,但是你从社区获得了关于你的编程技能的有价值的反馈,从长远来看,这可能对你有更大的帮助。
与他人建立联系,你不会后悔。
16.首先,让它工作,然后让它变得更好
照片由亚历克斯·科特利亚斯基在 Unsplash 上拍摄
“让它工作,让它正确,让它快。”—肯特·贝克
这条建议和你的初稿的建议是相辅相成的。用最少的句子来表达你的观点。稍后添加细节。首先,让它发挥作用。
拥有极简主义者的心态,以迭代和渐进的方式解决问题。迭代意味着你循环工作,迭代解决问题。增量意味着你在目前已经取得的成果的基础上继续努力。使用演绎或归纳的方法,但首先要让它起作用。
17.不要试图推销
莎伦·麦卡琴在 Unsplash 上的照片
“带着帮助客户解决问题或实现目标的想法接近他们,而不是销售产品或服务。”—布莱恩·特雷西
假设你购买了一款手机应用。你第一次启动它,只是为了看看它仍然包含恼人的弹出窗口和广告。你可能觉得被骗了。
中等文章也是如此。如果你在付费墙后发表文章,那么读者已经支付了费用,可以免费阅读这些文章。他们想要产品,仅此而已。不要因为包含附属链接和重复行动号召(CTA)而失去读者的信任。不要滥用你的文章以销售产品为主要目的。
只要努力解决他们的问题,销售就会随之而来。
18.把问题留在第二天解决
“熟能生巧。只有练习,再加上一夜的睡眠,才能达到完美。”—马修·沃克
乔希·考夫曼在他的书《前 20 小时:如何快速学习》中谈到了睡眠的重要性。他解释说,大多数学习过程不是在你练习的时候发生的,而是在你睡觉的时候。当你临睡前练习时,你会达到最好的效果。你的潜意识会处理剩下的。
即使你不在睡觉前写文章,当你被卡住的时候,在一个问题上睡觉几乎总是一个好主意。写作和编程都是创造性的工作,有时你就是无法推动它。
睡了一夜好觉后,你常常能想出一个简单的办法来解决一个看似困难的问题。
19.重构
“一个直观的定义是,安全重构是不会破坏程序的重构。因为重构的目的是在不改变程序行为的情况下重构程序,所以程序在重构后的表现应该和重构前一样。”—马丁·福勒
重构是软件工程师最常听到的一个术语。重构使代码更容易阅读,而功能保持不变。你可以把同样的原则应用于一般写作。
你可能以前听过这句话:“如果读起来容易,那么写起来就很难!”。但是几乎没有人第一次就写出优雅的句子。这是一个反复修改你的作品的过程,直到它易于阅读而不丢失主要信息。
有勇气去掉句子。让你的产品精益。
20.营销和分销
“如果一棵树倒在森林里,周围没有人听到,它会发出声音吗?—乔治·贝克莱
上面的引用很好地类比了写文章或创造任何类型的产品。你可能花了一些时间写你的文章。然而,如果一开始就没有人注意到它的存在,那该有多可悲?你所有的努力都会白费。
我最近写了一篇关于如何备份 WordPress 的文章。我在上面花了几天时间,但它没有被策划,也没有在任何地方发行。不要犯和我一样的错误。你正在阅读的这篇文章源于对我的 WordPress 文章的不满。
营销和分销几乎和产品本身一样重要。也许更重要。问问你自己:我怎样才能让尽可能多的人对我的产品感兴趣?
Medium 为此提供了不同的解决方案:
- 为你的文章使用合适的标签。如果你的文章得到了策划,那么它将会出现在它所策划的主题中。你文章的策展叫做“分发”。媒体有一定的指导方针来获得策划。
- 将你的文章提交给出版物。大部分都有写作指南。在提交文章之前,阅读它们并应用到你的文章中。
- 查找最活跃的媒体出版物,看看其中是否有合适的。
除了 Medium 的内置分发功能之外,您还可以在其他任何地方提交您的文章。搜索可能对你的内容感兴趣的在线社区,如 Reddit、论坛、脸书、Instagram。选择权在你。
最后的话
我希望你喜欢这篇文章。你可以根据自己的需要随意调整这个列表。如果您对本文有任何问题或评论,请在下面留下您的评论。
你对我的文章或项目的更新感兴趣吗?我的简讯每月一次让你了解最新消息!
如果你想支持我,并且你还不是一个中等会员,那么请考虑通过我的推荐页面注册:https://medium.com/@christoph.schmidl/membership
如何用 Python 编写 ETL 操作
使用 Python 清理原始数据并将其转换为可接受的格式
来源: Unsplash
在本文中,您将学习如何在 Python 环境中处理 Excel/CSV 文件,以清理原始数据并将其转换为更易于接受的格式。这对数据集成非常有用。
本例将涉及到许多常见的 ETL 操作,如过滤、减少、、、和展平。
笔记
这些例子的代码可以在 GitHub 这里上公开获得,还有我将带你浏览的镜像信息的描述。
这些示例依赖于两个开源 Python 包:
- pandas: 一个广泛使用的开源数据分析和操作工具。更多关于他们网站和 PyPi 的信息。
- gluestick: 一个小型开源 Python 包,包含由 hotglue 团队维护的用于 ETL 的 util 函数。更多关于 PyPi 和 GitHub 的信息。
事不宜迟,我们开始吧!
介绍
这个例子利用了来自 Quickbooks 沙盒环境的样本 Quickbooks 数据,并且最初是在一个 hotglue 环境中创建的——一个用于初创公司的轻量级数据集成工具。
请随时关注下面 GitHub 上的 Jupyter 笔记本!
用 Python 编写 ETL 转换脚本的简单示例
github.com](https://github.com/hotgluexyz/recipes/blob/master/src/basic.ipynb)
第一步:读取数据
让我们从读取数据开始。
这个例子建立在 hotglue 环境上,数据来自 Quickbooks。在 hotglue 中,数据以 CSV 格式放在本地的sync-output
文件夹中。我们将使用 gluestick 包通过read_csv_folder
函数将输入文件夹中的原始数据读入熊猫数据帧字典。
通过指定index_cols={'Invoice': 'DocNumber'}
,Invoices
数据帧将使用DocNumber
列作为索引。通过指定转换器,我们可以使用ast
来解析Line
和CustomField
列中的 JSON 数据。
偷看一眼
让我们看看我们正在处理哪些数据。为了简单起见,我选择了我想要使用的列,并将其保存到input_df
。通常在 hotglue 中,你可以使用一个字段映射来配置它,但是我在这里是手动完成的。
步骤 2:重命名列
让我们通过将列重命名为更易读的名称来清理数据。
CustomerRef__value -> CustomerId
CustomerRef__name -> Customer
MetaData_LastUpdatedTime -> LastUpdated
MetaData_CreateTime -> CreatedOn
CurrencyRef__name -> Currency
CurrencyRef__value -> CurrencyCode
第三步:提取信息
Line
列实际上是 Quickbooks 提供的一个序列化的 JSON 对象,其中有几个有用的元素。我们需要从展平JSON 开始,然后分解成唯一的列,这样我们就可以处理数据了。
同样,我们将使用 gluestick 包来完成这个任务。explode_json_to_rows
函数在一个步骤中处理展平和分解。为了避免分解这个对象的太多层次,我们将指定max_level=1
下面是其中的一个片段,可以让你有所了解。
[{
'Id': '1',
'LineNum': '1',
'Amount': 275.0,
'DetailType': 'SalesItemLineDetail',
'SalesItemLineDetail': {
'ItemRef': {
'value': '5',
'name': 'Rock Fountain'
},
'ItemAccountRef': {
'value': '79',
'name': 'Sales of Product Income'
},
'TaxCodeRef': {
'value': 'TAX',
'name': None
}
},
'SubTotalLineDetail': None,
'DiscountLineDetail': None
}]
步骤 4:筛选行
出于我们的目的,我们只想处理带有Line.DetailType
或SalesItemLineDetail
的行(我们不需要小计行)。这是一个常见的 ETL 操作,称为过滤,使用 pandas 很容易完成
第五步:更多爆炸
看看我们展开的Line
列中的一些条目。您会注意到它们是 JSON 中的名称值对。
让我们再次使用胶棒通过json_tuple_to_cols
功能将这些分解成新的列。我们需要指定lookup_keys
——在我们的例子中,是key_prop=name
和value_prop=value
第六步:更多爆炸
看一下CustomField
栏。下面是一个条目示例
[{'DefinitionId': '1', 'Name': 'Crew #', 'Type': 'StringType', 'StringValue': '102'}]
您可以看到这是 JSON 编码的数据,指定了一个定制字段:Crew #
,值为102
为了分解这个,我们需要减少这个,因为我们只关心Name
和StringValue
。我们可以使用 gluestick 的explode_json_to_cols
功能和array_to_dict_reducer
来完成这个任务。
结论
我们的最终数据如下所示。在这个示例中,我们使用一个真实世界的例子,使用基本的 Python 工具完成了几个基本的 ETL 操作。
将来,你可以随意查看开源的热熔胶配方以获得更多的样本。感谢阅读!
如何写好科技文章
回顾:这不是关于神经衰弱
没有成功的秘诀。但是有些事情是有帮助的。布鲁斯·马斯在 Unsplash 上的照片
当我开始写作时,我没有想到我的文章会被翻译成几种语言,获得数百万的浏览量和数千美元的收入。那不是我开始时的目标。但是我不能抱怨。
成功没有唯一的秘诀。如果有的话,那么每个人都会在他们的游艇上放松,在夕阳下啜饮鸡尾酒。
但有几件事我从一开始就明白了。这不是关于精心制作一个完美的标题或获得正确的搜索引擎优化。造成这种差异的更多的是我在这背后的总体心态。在培养基上经历了六个月的巨大成长后,这就是我的工作。
1.想办法
我开始在媒体上写作,因为我不想在周日工作,但我需要做一些有意义的事情。但是我没有写任何东西,而是思考我是谁,我想代表什么。
我正在攻读物理学博士学位,所以写关于科学和研究的文章似乎是一个显而易见的选择。我也是同性恋,所以我想我可以分享我作为一个边缘人在科学方面的经历。但是我发现写我的个人生活真的很难,所以我没有写太多关于 LGBTQIA 的问题。
当你现在看我写的文章时,你会注意到我甚至没有写很多关于科学的东西——更多的是关于数据科学和编程语言。我没有像奴隶一样坚持我的计划。这更像是我灵媒之旅的起点。
这就是计划的作用。无论你的计划有多好,它都可能撑不过你写作的第一个月。但是它让你思考什么对你重要,你想写什么。它给你一个最初的方向,可以而且应该随着时间的推移而发展。
2.保持一致
你的第一篇文章不会是杰作。你的第二个也不会。即使你的十分之一也不会传播开来。
如果你的梦想是写一部轰动一时的作品,一夜之间成为百万富翁,请三思。媒体上最成功的作家多年来一直在大量创作作品。有些是每天,有些是隔天,有些是每周。但是你可以打赌,他们会在这个星期,下个星期,再下个星期出版。
我最初的目标是每周发布一个故事。我从 12 月份开始,我坚持每周一次的计划,度过了圣诞节的喧嚣和生活中所有其他令人分心的事情。
你一定要出现。每一次。
时不时休息一下没关系——我自己也休息过几次,因为冠状病毒危机中的生活充满挑战。如果你需要休息,不要因为休息而责备自己。但是请记住,如果你想成功,写作应该在你的优先事项清单上保持首要位置。
3.看看什么能打动你的观众
在我开始写作大约一个月后,我意识到大多数读者喜欢关于人工智能的东西。所以我写了更多关于这个的东西。
然后我意识到阅读我的东西的人是程序员和数据科学家,所以我开始写这方面的东西。那时我制作了我的第一批热门歌曲:
你的小众可能不一样,你的受众也可能不一样。我想我应该为各行各业碰巧对科学感兴趣的人写作。但是我是为程序员写的。
看看你的统计数据,看看哪些故事起飞。如果你想要大量的读者,这给了你很多关于为谁写的线索。
也就是说,只写你真正热爱的东西。如果你的目标是用你不在乎的东西取悦每个人,人们会看穿的。
表达你的观点,即使很尖锐。承担风险。永远忠于自己。有趣的是,从长远来看,这会让你更成功。
你的观众喜欢什么?照片由尼古拉斯·格林在 Unsplash 上拍摄
4.明智地选择你的 KPI
看看你获得了多少浏览量或者一个故事获得了多少掌声是很好的。你可以从中了解很多关于你的听众的情况。
但是不要纠结于你的数据。选择几个关键的绩效指标,剩下的留给你有时间时的额外见解。
我的 KPI 是合作伙伴计划收入和关注者数量。追随你的人是经常性读者,因此对未来的成功来说,比你目前获得的观点更重要。收入——嗯,我想我喜欢赚钱。
我保存了一个漂亮的小电子表格,记录了每周的关注人数。我每天都记下当月的收入。这不仅让我对是什么带来了金钱有了一些很好的见解——早上醒来,意识到你刚刚在一夜之间赚了几百美元,这也是一种很好的感觉。
5.对机会说“是”
写作一个月后,我开始接触媒体上的出版物。将你的作品添加到出版物中不需要花费任何成本,并且让你的作品受到很多新的关注。所以我答应了。
又过了一个月,其他平台开始联系我,问我他们能否将我的文章翻译成其他语言,并在他们的网站上展示。这不花我一分钱,我还可以免费曝光。所以我答应了。
在我成为作家的四个月里,其他平台开始联系我,希望从我这里获得独家内容。这次我并不总是同意——如果我在 Medium 上发表一篇可以赚几千美元的文章,那么我要么想要同样多的钱,要么想接触一些了不起的人。
根据经验,无论你遇到什么,我都会答应。你永远不知道这会给你带来什么。如果你不喜欢它,因为人们很差劲,或者因为它不够赚钱,你以后仍然可以放弃它。
感激出现在你面前的人和机会。戴安娜·西姆潘德在 Unsplash 上的照片
6.忠于你的人际网络
如果没有其他作者、平台编辑和媒体内外其他人的支持,我的成功是不可能的。
这包括 Ludovic Benistant,他首先发现了我的作品,并邀请我为数据科学的 T2 撰写文章。这包括安妮·邦纳,她是 TDS 上一名出色的编辑。这包括叮当(洪静),她作为编辑和作家都很可爱。以及更多的人。
我确保定期检查他们的工作,并进一步推荐。我给他们掌声和关注,因为他们值得,并在媒体和其他社交媒体上交换意见。
无论你在职业生涯的哪个阶段,回馈都不会太早。让人们知道他们对你很重要。试着帮助他们追求目标,就像他们帮助你一样。你的关系网就是你的净资产。
7.不要把仇恨者看得太重
一旦你获得了一些关注,很有可能你会得到一堆负面的评论。这确实取决于你写的内容和你是否具有煽动性(哎呀,我对此感到内疚)。
看看我最受欢迎的两篇文章的评论部分:
他们充满了仇恨!我可以把它们藏起来,但我更喜欢让人们自己做决定。
而且看那些评论很伤人。不管你有多冷酷,那也不会让你心情愉快。
我不建议你完全远离评论区。你的读者是你作为一个作家存在的理由,所以你应该更加认真地对待他们。他们确实提供了建设性的批评,新的想法,和各种令人敬畏的东西。
但是也有一些人喜欢在他们阅读的所有东西下面写一些充满仇恨的东西。我喜欢认为我的故事对他们来说一定很重要,因为他们花了五分钟写了一篇评论。
感受你的感受,然后继续前进。不要让那些人打击你。
没有必要重新发明这些!乔恩·卡塔赫纳在 Unsplash 上拍摄的照片
8.不要多此一举
当写作时间来临时,我经常有很多想法要写些什么。我从我的生活、我当前的项目、与周围人的对话等等中收集了它们。
但是有时候我不知道该写些什么。我收集的所有材料似乎都不够鼓舞人心或及时,我坐在一个空白的屏幕前,不知道该做什么。
有趣的是,我在这样的时刻——或者几个小时之后——发表了我最受欢迎的故事。我通常花 30 分钟左右的时间来尝试自己想出一些东西。
但是如果我什么都没找到,我就在我的故事的评论中梳理,并通过 Twitter 和 StackOverflow 进行检查。那里有很多东西。
之后,我用谷歌搜索我的标题,看看它是否填补了一个空白。如果这是一个还没有人写过的利基市场,那太好了!但是如果有很多关于这个话题的文章,那也没关系。
你不需要每次都重新发明轮子。只要确保你给你的同行作家应有的尊重,并链接到他们的文章。
9.看别人的东西
如果你想飞黄腾达,就向最伟大的人学习。Medium 上有一些非常棒的东西,你可以从中学习一些东西。
你可以学习如何写能引起共鸣的文章,震撼人心的标题,形成自己的风格。可以了解当下流行什么,读者想听什么。你可以了解你的利基或完全不同的东西。
你看看我突出和拍手的是什么,都是各种东西。大部分甚至不是面向技术的。尽管我出于个人兴趣阅读了这些故事中的大部分,但我总能从它们中找到提高我写作水平的教训。
我写关于技术的文章,但我不想听起来像个书呆子。我想听起来像我一样。阅读各种主题是关键。
如果你读了很棒的东西,那会以这样或那样的方式给你的写作增加价值。要么你从内容中学到东西。或者你从风格中学到一些东西。
永远不要停止学习。摄粘土堤上的 Unsplash
10.不断学习
在写建议方面,永远不要停止学习。你不需要阅读建议文章——只需要从你阅读和喜欢的东西中吸取教训。
以下是我在媒体上写作时学到的一些重要经验:
- 话题就是一切。如果你就一个不相关的话题写了一篇漂亮的文章,没人会看。
- 如果你太努力去写人们喜欢的东西,没人会看的。在这种情况下,写下与他们想听到的相反的内容。我迄今为止最受欢迎的文章——关于为什么 Python 不是永远的——奏效了,因为人们爱上了 Python。
- 短句总是胜过长句。
- 比起大段大段的文字,更喜欢小段落。一句俏皮话没问题。
- 副词烂。你认为他们强化了你的观点,但他们却弱化了它。尽可能把副词踢出去。
- 如果使用得当,f-bomb 和其他脏话是没问题的。
- 只要它们不是无脑的,就没问题。但是不要只写列表条。
- 你不需要成为每个人的宠儿。你的敌人暗地里爱着你,只是他们不承认罢了。
只要我还是一个有大脑的人,这个清单就会越来越长,因为人类的大脑喜欢学习。你可以通过有意识的学习来最大化你的学习成果。
创建内容的简单技巧,易于查找,阅读起来令人兴奋
medium.com](https://medium.com/swlh/how-to-write-and-publish-articles-that-get-noticed-60e9701daed4)
最后一句话:耐心点
大多数时候,我醒来发现自己一夜之间又赚了几百美元。但这并不是一夜之间发生的,听起来很矛盾。
2019 年 12 月,赚了 55 美分。2020 年 1 月,我得到了 20 美元。二月份是 120 美元。从三月份开始,我就收到了一张四位数的支票和 50 万的月浏览量。
当然,我为此很努力,但我想我也很幸运。我在正确的时间开始,在正确的出版物上发表,接触到正确的读者。媒介对我来说是一个完美的机会。
你的成功将取决于你写了什么,你有什么样的风格,以及你是否与你的 sh*t 保持一致。一开始,当你的故事得到 20 个观众时,你会很高兴。许多个月后,你会想,当一个故事只有 2k 时,哪里出了问题。
无论你在旅途中的什么地方,成功都会到来,因为你每天起床,全身心地投入到你热爱的事情中。很有可能,其他人也会喜欢这些东西。在媒体上,在生活中的任何地方。所以快下来写吧。