Extracted main text — title through conclusion, appendix excluded. This is what our citation measures are computed over, published so the extraction can be checked by eye.
53,212 characters · 12 sections · 66 citation commands
The study of occupational outcomes requires systematic data on people's occupations, and the Historical International Standard Classification of Occupations (HISCO) system has emerged as the standard for categorizing diverse historical occupational data leeuwen2002hisco. However, the manual classification of large datasets into HISCO codes has been an arduous and time-consuming process, hampering research progress. A simple back-of-the-envelope exercise illustrates the scale of the problem: Even a highly experienced researcher might spend 10 seconds identifying and typing the correct HISCO code for an occupational description. Thus, coding 10,000 unique descriptions would take around 28 hours of manual labor. In datasets with hundreds of thousands, or even millions, of descriptions, a manual approach quickly becomes infeasible.
In this paper, we present a solution that transforms the task of coding occupations into something that can be completed automatically in minutes or a few hours, including verification of quality. We introduce OccCANINE---a small transformer-based language model built on the CANINE model by Clark2022CANINE---which we finetune on 15.8 million observations of occupational descriptions paired with HISCO codes across 13 languages. This training data was generously contributed by numerous researchers and cover 29 different sources, each of which is cited in Table (ref). The resulting model achieves high accuracy, precision, and recall, and can reliably transform raw textual descriptions of occupations into the most appropriate HISCO codes.
The HISCO system was introduced to produce internationally comparable historical occupational data. It, and its various modifications, has since become the most widely used classification scheme for historical occupations, though other schemes remain in use. While this paper focuses on solving the problem of HISCO coding, the method readily extends to other systems. We demonstrate this by also training and releasing OccCANINE models for the OCC1950 classification system (used in US historical censuses), the OCCICEM classification system (used in British censuses), and the ISCO-68 classification system (the international system from which HISCO is derived). The lesson is clear: OccCANINE provides a general solution to the problem of occupational coding.
By significantly reducing the time and effort required for HISCO coding, our tool democratizes access to historical occupational data. This enables researchers to conduct more extensive and diverse studies while devoting more attention to data quality. This breakthrough has the potential to unlock new insights into occupational trends and shifts over time, contributing valuable knowledge to economics, sociology, political science, history, and related disciplines. Moreover, the paper provides a general recipe for tackling a wide range of similar problems in which large volumes of unstructured text must be mapped into standardized systems. Comparable challenges exist in coding historical customs records, educational descriptions, and many other sources, all of which can be addressed with a similar approach.
The remainder of this paper proceeds as follows. Section (ref) motivates our solution. Section (ref) outlines the model architecture, training data, and training procedure. Section (ref) evaluates performance. Section (ref) discusses how to use OccCANINE in settings where model performance proves inadequate. Section (ref) concludes with recommendations on how to use OccCANINE.
To generate insights into topics such as women's empowerment Goldin2006, social mobility Clark2023, the effects of railways Berger2019Railways, gorges2025tracksmodernityrailroadsgrowth, first-nature geography Vedel2023, the origins of the Industrial Revolution Allen2009, and the interplay of technology and development Morkyr2016, we need reliable information on people's occupations. This motivates the collection of large-scale datasets of historical occupational data. Much of this information comes in the form of long lists of textual descriptions (e.g., census records or marriage certificates). An example could be “Lives of fishing and farm work,” which would need to be converted into standardized occupational categories (61110: “Farmer” and 64100: “Fisherman” in the HISCO system).
The challenge of transforming raw textual occupational descriptions into standardized categories is not trivial, requiring either extensive manual work by error-prone research assistants or sophisticated methods from the classical natural language processing toolbox. In particular, the diversity of occupational descriptions is problematic.\footnote{For example, the Danish censuses 1787–1901 LinkLives2022Guide, ddd_method2015 contain no fewer than 17,865 unique descriptions corresponding to the occupation “farm servant.” See Schurer2015 for similar challenges in coding British censuses.} The traditional approach to HISCO coding involves string matching and cleaning using, for instance, regular expressions. Because of negations, changing spelling conventions, typos, and transcription errors, this process quickly becomes complex and error-prone. Typically, the following steps are involved:
This pipeline must be repeated for every single source, with little scope for generalizability. Our OccCANINE model replaces all of these steps and provides significantly greater robustness across data sources.
The primary barrier is that prior solutions treat occupational coding as surface-level string matching rather than semantic understanding. This root problem makes them slow, inaccurate, unscalable, and unable to generalize across different data sources. Our solution breaks this barrier by treating occupational coding as an end-to-end prediction problem. We train a small language model to understand occupational descriptions as a person would. Specifically, we finetune a preexisting language model on 15.8 million pairs of occupational descriptions and HISCO codes. The resulting model inherently captures the occupational meaning of descriptions, allowing it to process inputs with typos, spelling mistakes, or other irregularities. The model then (similar in spirit to ChatGPT, but smaller) draws on its multilingual knowledge of language and similarity to output the appropriate HISCO code(s). In effect, all the steps described in Section (ref) are reduced to a single step: the input is a raw occupational description (and optionally a language), and the output is the relevant HISCO code(s). Figure (ref) illustrates our approach at a high level, which has the following advantages:
The chronological improvement in performance demonstrates the rapid underlying technological development that now allows the simple method we propose in this paper. To set the stage, we provide a brief overview of recent developments.
A central term in this literature is the production rate: the share of occupational descriptions one chooses to automatically transcribe (with the remainder left to a human labeler). This is typically done by only automatically transcribing observations for which a label is assigned with the highest probability (e.g., an 80 percent production rate means that the algorithm produces codes for 80 percent of the samples, while humans produce labels for the remaining 20 percent). Early approaches perform well only at lower production rates. Patel2012Performance demonstrate 89 percent agreement with a human labeler at a 71 percent production rate, relying mainly on rule-based, classical NLP approaches. Gweon2017 propose combining rule-based methods with bag-of-words cosine distance and nearest-neighbors matching. For “fully automatic labeling” (100 percent production rate), they achieve 65 percent accuracy on German survey data for the ISCO-88 system (which is similar to the HISCO system), and recommend using the method at lower production rates where performance is higher.\footnote{To achieve 90 percent accuracy, Gweon2017 require around 40 percent manual labeling.} Schierholz2020 review this and other machine-learning approaches to automatic occupational labeling. Using boosting trees, they demonstrate around 78 percent agreement at a 100 percent production rate. turrell2019transforming propose a heuristics-based method with a production rate of 34 percent for which it agreed 91 percent of the time with a human labeler. heijden2022 uses features extracted from financial statements and a random forest to predict a standard industry classification, achieving an F1-score of 89 percent.
More recent work builds on Transformers vaswani2017attention, including pre-trained models such as BERT devlin2018bert. SuarezGarcia2021 implement a method that combines traditional exact matching and data-cleaning techniques with advanced text analysis (including TF–IDF and Doc2Vec, utilizing BERT) for cases without exact matches. Applied within a conventional machine-learning framework, they report a macro F1-score of 0.65 and a top-5 per-digit macro F1-score of 0.76 in the Canadian National Occupational Classification Scheme. muhlbach2022occ2vec, instead of classifying occupations, develops an embedding approach (a high-dimensional semantic representation) from which useful information about any occupation can be extracted. Our method implicitly contains this as well, in the final representation internally in our model before the classification step.
The research most comparable to ours is conducted by Safikhani2023BERT, who finetune German BERT and GPT-3 on 47{,}526 observations of German survey data to classify them into the German KldB system. They report a maximum Cohen's kappa of 64.22 percent for the full occupational code in their test data.\footnote{Cohen's kappa is roughly comparable to accuracy but accounts for chance agreement.} As a comparison, Schierholz2020 achieve 48.5 percent Cohen's kappa on the same test data. To the extent that our data are comparable, we outperform these results by a large margin, achieving 96.1 percent accuracy and a 96.3 percent F1-score on our test data. In many cases, this allows us to disregard lower levels of “production rate,” as it is barely relevant at this level of performance. Moreover, our method requires no string cleaning, correction of spelling mistakes, or stop-word removal.
We make use of the CANINE architecture Clark2022CANINE, a relatively small (127 million parameter) language model based on the transformer architecture vaswani2017attention. Modest-sized models often outperform larger models in specialized prediction tasks bucher2024smallLMstill, while also offering faster and cheaper inference. CANINE was pre-trained on Wikipedia data across 104 languages. Our choice of this architecture is motivated by three factors. First, Wikipedia pre-training ensures multilingual capabilities, and it is reasonable to assume some similarity between historical occupational descriptions and Wikipedia text. Second, we want the model to be broadly accessible. It is small enough to run (and even finetune modestly) on a common laptop. Third, the model uses character-level tokenization. The most commonly used tokenization approaches operate at the wordpiece level, but for archival data this can induce unnecessary model variance. For example, if “farmer” is mistyped as “frmter,” traditional tokenization may struggle. The CANINE architecture is more robust to this type of variation.
Figure (ref) presents the practical implementation of the conceptual model in Figure (ref). We input an occupational description (and optionally a language). CANINE (the “Encoder”) is then used to obtain a numerical representation of this text string.\footnote{In our default implementation, the encoder produces a high-dimensional representation (a padded sequence of $128 \times 768$ hidden states), which can be summarized into a $768$-dimensional embedding.} These numbers are not directly interpretable, but theoretically, they represent all the information needed to decide on the most relevant HISCO code(s) for the given occupational description. To obtain the HISCO code(s), we have to decode this representation. We do this with a “Decoder” module that translates the numerical representation into HISCO code(s).
For OccCANINE, we implement two decoder modules: (A) a Flat Decoder and (B) a Sequential Decoder.\footnote{In the accompanying OccCANINE Python package, these options are exposed via the shorthands fast (Flat) and good (Sequential).} The Flat Decoder is designed for speed and produces a short list of likely HISCO code(s) for each description. The Sequential Decoder, instead, constructs HISCO code(s) digit by digit, which makes it more robust to ambiguity and multi-occupation descriptions out-of-the-box. A practical advantage of the Sequential Decoder is that it predicts one digit at a time, so each step involves a much smaller search space than choosing among all full HISCO codes at once, which makes model training more efficient. The Flat Decoder requires that researchers pick a confidence threshold (a cutoff for when a predicted code is accepted), while this is implicitly handled by the Sequential Decoder. For this reason, we generally recommend the Sequential Decoder for most applications, while the Flat Decoder remains an efficient alternative when computational resources are limited. Appendix (ref) provides the full illustration of the architecture and implementation details, including decoder dimensionalities, the probability-to-prediction mapping for the Flat Decoder, and the decoding procedures (greedy and top-$k$) used with the Sequential Decoder.
This project utilizes training data obtained from public sources or generously provided by fellow researchers, for which we express our gratitude (see Table (ref) for a complete list). We process all sources through a common pipeline---character normalization, source-specific quality checks, and validation of HISCO codes---and we additionally augment the data with simple conjunction-based multi-occupation phrases. Appendix (ref) summarizes the key steps, and the complete implementation is available in our GitHub repository.
In total, the data consist of 18.5 million observations. Of these, 85 percent (15.8 million) are used for training. The remainder is split across in-training validation (5 percent), post-training validation for model development (5 percent), and final model testing (5 percent). To ensure representativeness across all splits, we stratify by data source. We further conduct out-of-distribution (OOD) evaluation using entirely different data sources. To improve robustness, we apply additional data augmentation as part of training; Appendix (ref) provides details.
The architecture described above has a total of 151 million parameters---when including both encoder and decoder. Model training is performed in random batches of 512 observations over 1{,}605{,}000 steps. That is, the model “sees” the full training data around 50 times, and we adjust parameters step by step accordingly. We also apply a few standard regularization and data-augmentation techniques. We use 10 percent dropout srivastava2014dropout, random text augmentation, and occasional “hiding” of the language label, so the model learns to make predictions even when this information is unavailable. All of this helps produce a more robust model. Appendix (ref) reports the exact settings.
A limitation of some training data is that occupational codes in the labels are not consistently ordered across samples. For example, “he fishes and farms” might be coded as either [61110: “General farmer”, 64100: “Fisherman”] or [64100: “Fisherman”, 61110: “General farmer”]. This is not inherently problematic, since our objective is to detect all occupations present in a description regardless of order. However, it poses a challenge for our Sequential Decoder, where output order matters. We address this by introducing a novel loss function invariant to the order of predictions. This loss function might be useful for other researchers facing similar problems. See Appendix (ref) for technical details.
\FloatBarrier
We evaluate performance on a held-out test set of 931{,}474 observations (5 percent, not used in training) in Table (ref). We report accuracy (with partial credit for partial matches), precision, recall, and F1-score. For observations that may have several valid codes, we evaluate precision and recall per observation by comparing the predicted and true sets of codes, compute an F1-score for each observation, and then report the average across all observations; see Appendix (ref) for details. At the 5-digit level, the Sequential Decoder achieves 96.1 percent accuracy, 96.1 percent precision, 96.7 percent recall, and a 96.3 percent F1-score.\footnote{A natural concern is that high test performance could partly reflect memorization of very common occupational strings that, by sheer chance, appear in both training and test splits (e.g., “farmer”). Since such strings also occur frequently in genuinely new corpora, removing them understates expected real-world performance. Nevertheless, as a deliberately conservative robustness check, we evaluate on a test subset consisting of strings that never appear in the training data. On this “guaranteed new strings” subset, performance remains around 80 percent at the five-digit level across our main metrics, indicating that the model’s accuracy is not driven by overlap in surface forms.} The Flat Decoder reaches similar performance, but this comes at the cost of requiring threshold tuning. We do this with a grid-search of thresholds from 0.01 to 0.99 on the 926{,}454 validation observations.\footnote{Appendix (ref) (Table (ref)) reports language-specific optima. Results here use the globally optimal thresholds that maximize F1-scores.}
To assess the value of optional language context, we compare OccCANINE with and without language information (Table (ref)). Providing language yields a small but consistent improvement; without it, performance remains robust, indicating a multilingual conceptual understanding of occupations. Appendix (ref) (Figure (ref)) shows (i) that performance is strong across all 13 trained languages and (ii) the robustness to omitting language information holds across languages.
OccCANINE also achieves relatively fast performance. To benchmark real use cases, we tested our model on 10,000 observations on one of our laptops---mimicking what is available for researchers with a laptop equipped with a GPU. On a Windows machine with an NVIDIA Quadro T2000 4GB GPU, we are capable of predicting 10,000 HISCO codes in 8 minutes and 56 seconds for the Sequential decoder and 1 minute and 38 seconds using the Flat decoder. In comparison, at 10 seconds per observation, this would take a human labeler 27.5 hours.
\FloatBarrier OccCANINE can only learn the patterns provided in the generously contributed training data shown in Table (ref). Yet HISCO coding itself is not free of ambiguity: whether a person belongs to one category or another is sometimes open to interpretation. For example, there are separate codes for “Policemen and Detectives” and for “Policemen and other Maintainers of Law and Order (except Military).” Our expectation is that, in ambiguous cases, the judgment calls made by human labelers are more often reasonable than not. This would provide more of the correct training signal than the incorrect one. For this reason, it is particularly interesting to examine whether OccCANINE agrees with human labelers from other sources and research projects beyond our training data. We therefore extensively test out-of-distribution (OOD) performance on two distinct groups of corpora. Table (ref) reports accuracy and agreement rates on samples we manually validated (i.e., with no pre-existing HISCO codes), while Table (ref) reports agreement rates with samples that already had HISCO codes assigned (but from sources we did not include in our training data).
The results in Tables (ref) and (ref) show that OccCANINE achieves high accuracy both in manually checked datasets and in already labeled datasets, despite potential disagreements. For the manually validated cases, we compare the predicted HISCO codes with the definitions and classify them as either (i) strictly correct, (ii) substantially accurate (closely related but not exact), or (iii) incorrect.\footnote{For example, in the Norwegian Biographies we observe an “engineer and estate owner” (ingeniør og godseier). OccCANINE labels this as “02000 Engineer, Specialisation Unknown” and “61110 General Farmer.” Since the second code may not be fully appropriate, we classify the result as substantially accurate but not strictly accurate.} Across the two cases shown, OccCANINE achieves between 87 and 96 percent accuracy depending on the strictness of the definition.
For the samples that already contained HISCO codes, we use these as the reference. The results are shown in Table (ref), where we report "agreement rates," noting that HISCO is not entirely unambiguous. In some cases, OccCANINE’s prediction may be just as valid as the source label, even when the two do not match. Looking at the results, OccCANINE performs strongly on the Swedish and Dutch datasets, where ample training data exist. By contrast, performance is lower on the Danish West Indies (mostly English) and UK Bankruptcies sources. A likely explanation is that HISCO codes in these cases were generated with regex-based pipelines, which are brittle and sometimes miss uncommon or compound professions; as a result, genuine occupations were occasionally recorded as $-1$ (“no occupation”) despite this not being appropriate (as we confirm by manual checks). Excluding these cases substantially raises agreement rates (Panel B), suggesting that most residual gaps reflect label coverage rather than model error. For the Italian and German datasets, agreement rates are somewhat lower, which is unsurprising given the limited training data in these languages. Still, the results are encouraging. Even with sparse training material and without any source-specific engineering, OccCANINE achieves agreement that appears competitive with the practical alternatives suggested by the literature review, and it provides a useful baseline that can be improved further with light fine-tuning where needed.
To better understand why OccCANINE generalizes across diverse sources, we visualize its encoder embeddings. Encoder embeddings are the model’s internal numerical representations of each occupational description, summarizing the information it uses to predict HISCO codes. When reduced from 768 to two dimensions, occupations cluster naturally by sector, indicating that the model has developed a meaningful semantic representation of historical work (Appendix (ref)).
We also evaluate model performance across frequency of occupational categories. As expected, accuracy is highest for the most common HISCO codes, while performance gradually declines for rarer ones---a pattern typical in multiclass classification. For the vast majority of codes (the most frequent 99 percent), performance remains very strong, and even for the rarest occupations, average accuracy is still close to 90 percent (Appendix (ref)). A natural concern is whether this decline in performance might systematically correlate with socio-economic status (SES). Appendix (ref) shows a weak negative association between SES and performance ($\sim$0.05 percentage points lower accuracy per 1-point increase in HISCAM), but this effect is no longer statistically significant once we control for the number of training observations per code. This suggests that the apparent SES effect is driven primarily by the relative scarcity of training data for certain high-SES occupations. In practice, the effect size is negligible, but we nevertheless encourage users to remain attentive to possible systematic biases in sensitive applications. In particular, we recommend plug-and-play approaches based on validation data such as Prediction Powered Inference Angelopoulos2023PPI or Design-based Supervised Learning egami2024dsl.
Finally, we demonstrate that the approach is both portable and practical for related problems. Table (ref) reports transfer learning performance on three widely used systems---OCCICEM (British censuses), OCC1950 (U.S. historical censuses), and ISCO-68.\footnote{Source: IPUMS, Bureau of the Census, Office of National Statistics.} Finetuning on large training sets yields accuracies of 85.8–97.5 percent. A natural concern is that researchers may lack sufficient labeled data or access to large-scale computational resources. To address this, we benchmark finetuning under tighter data and compute budgets. We sample 10,000 observations---an amount that small teams could plausibly label. As shown in Table (ref), Panel B, accuracy remains solid at 80.6–85.4 percent. We also test a variant that freezes the encoder and finetunes only the decoder (Figure (ref)), reducing training time to about 20 hours while preserving performance (Table (ref), Panel C). Two conclusions follow: First, strong performance is attainable even for classification systems other than HISCO. Second, researchers can start with a modest labeled set of 10,000 descriptions, finetune the model, and then use OccCANINE to label additional data, which can be corrected and leveraged for iterative improvement.
Beyond fully automatic coding, the Sequential Decoder also supports top-\(k\) decoding, where the model produces a short ranked list of candidate HISCO codes and a human selects the correct one. This is useful when full automation is not appropriate but fast, high-quality standardization is still the goal. Figure (ref) summarizes the average pattern: Most gains arrive quickly for small \(k\), with diminishing returns thereafter. For example, while the probability of returning the correct HISCO code(s) is around 96 percent, if we allow the model to produce just two suggestions, one of them will be the correct HISCO code(s) in more than 98 percent of cases. The steep improvement from \(k=1\) to \(k=2\) is also informative about model failures. If errors were typically far off (meaning the correct HISCO code had very low model probability) then adding a second candidate would almost never “catch” the truth, and top-\(k\) performance would change little between \(k=1\) and \(k=2\). The fact that performance jumps at \(k=2\) therefore implies that many errors are near misses. The model confuses the correct code with a small set of highly plausible alternatives.
\FloatBarrier
Despite generally promising benchmarks, users will encounter applications with materially lower accuracy. This is clear in our out-of-domain evaluations (Tables (ref) and (ref)), where domain shift, short or ambiguous strings, and local coding conventions can reduce agreement. Researchers should therefore think explicitly about what level of accuracy is sufficient for their particular use case, and quickly validate performance on at least 100 randomly sampled observations from the target corpus. If that check suggests that performance is inadequate for full automation, OccCANINE still offers several practical routes to high-quality assisted coding. This section summarizes a simple escalation strategy.
A first lever is to run at a lower production rate. When error costs are high, it is rarely optimal to auto-code everything. Instead, accept only predictions above a confidence cutoff and route the remainder to manual review. The point is not to hide uncertainty, but to surface it and use it to prioritize human time. Appendix (ref) visualizes the trade-off between coverage and performance as the cutoff is tightened. A pragmatic workflow is to run the model once, sort predictions by confidence, validate a small sample around the intended cutoff, and then choose a cutoff that matches either an accuracy target or a review budget.
If the goal is fast, high-quality standardization (rather than full automation), top-\(k\) decoding is a practical middle ground. Rather than committing to a single code, the model proposes the \(k\) most likely candidates (e.g., \(k=2\) or \(k=5\)), which a human can select from. This is particularly useful for low-confidence cases, where the correct code is often among the highest-ranked alternatives even when the top prediction is wrong. Figure (ref) illustrates that most gains arrive immediately when moving beyond greedy decoding, with diminishing returns as \(k\) grows. Appendix (ref) documents how these gains vary across languages and out-of-domain datasets (Tables (ref) and (ref), respectively).
When low performance is systematic (e.g., consistent domain shift, a different coding tradition, or a different target classification), thresholding and top-\(k\) can help, but they do not change what the model has learned. In that case, finetuning on a project-specific labeled set is the right solution. Table (ref) shows that useful performance is attainable even with a modest labeled sample, and that freezing the encoder can materially reduce training time. A pragmatic approach is to start with a few thousand validated strings, finetune, use the improved model to generate preliminary labels on a larger batch, and then iterate as needed.
\FloatBarrier
We set out to remove a large bottleneck for progress in economic history and related disciplines. Large-scale occupational coding is slow and error-prone to do by hand. By training a small multilingual transformer on 15.8 million labeled description-code pairs, OccCANINE delivers around 96% five-digit accuracy on a held-out test set (and strong out-of-domain performance), turning what would otherwise be weeks of manual work into automated coding in minutes.
For most applications, we recommend using the Sequential Decoder. It achieves performance similar to the Flat Decoder while avoiding explicit threshold selection, which simplifies deployment and reporting. If computational resources are limited, the Flat Decoder remains an efficient alternative. For the Flat Decoder, we recommend a classification threshold of 0.26 to optimize the F1 score and 0.39 to maximize accuracy, based on performance on validation observations. Appendix (ref) provides language-specific thresholds. A step-by-step guide for applying OccCANINE is available in the code repository.
We hope that the freed resources can be used both to scale up research and to improve the quality of work involving standardized historical occupational data. Encouragingly, our method is already powering new and exciting studies.\footnote{Examples include Vedel2023, andersson2025ascending, chilosi2025smithian, gorges2025tracksmodernityrailroadsgrowth, ford2025origins, Bentzen2024Assimilate, proffit2025linking.} But we do caution that our method is not perfect. We strongly encourage researchers to validate at least 100 observations and report the achieved accuracy in any publication using our model. This practice enhances transparency, provides readers with a concrete measure of model performance, and underscores the uncertainties inherent in data work. In most cases, we expect that validation checks will confirm the adequacy of the predictions out of the box, or reveal that minor adjustments are sufficient. Where necessary, we also provide a framework for finetuning with a small set of validated observations. We intend to maintain and improve the model, and we encourage anyone using OccCANINE to reach out with questions, feedback, and additional data that may help train future versions.
As shown, our approach also transfers well to other classification systems (OCC1950, OCCICEM, ISCO-68), and we suggest that future research extend these efforts. We also see potential for related classification problems, such as coding goods in trade archives, education in biographical sources, or diseases in medical records. While 10,000 observations currently seem a practical starting point for finetuning, future work may also focus on developing more efficient training procedures.
In conclusion, OccCANINE represents a significant stride in historical occupational data processing, effectively breaking the HISCO barrier. By automating the translation of occupational descriptions into HISCO codes with high accuracy, our model reduces the costs of working with historical sources and opens new possibilities for research in economics, history, sociology, and beyond.
\setcounter{table}{0} \setcounter{figure}{0} \pagenumbering{roman}